Share
Embed
Django Tricks (2)
Curso de aplicaciones adicionales a tener en cuenta para un proyecto Django:
* django-crispy-forms
* south
* Pruebas y Selenium
Carlos Hernando
November 15, 2012
Transcript
43 slides
-
Crispy forms! {% load crispy_forms_tags %} <form method="post" class="form-horizontal"> {{
my_formset|crispy }} </form> -
Crispy forms! {% load crispy_forms_tags %} <form method="post" class="form-horizontal"> {{
my_formset|crispy }} </form> El formulario es compatible Twitter Bootstrap -
Un formulario from crispy_forms.helper import FormHelper class ExampleForm(forms.Form): [...] def
__init__(self, *args, **kwargs): self.helper = FormHelper() super(ExampleForm, self).__init__(*args, **kwargs) -
Personalizamos el formulario [...] self.helper.form_id = 'id-exampleForm' self.helper.form_class = 'blueForms'
self.helper.form_method = 'post' self.helper.form_action = 'submit_survey' self.helper.add_input(Submit('submit', 'Submit')) -
Y el template queda {% load crispy_forms_tags %} {% crispy
example_form %} -
Aún más personalizado from crispy_forms.layout import Layout, Fieldset, ButtonHolder, Submit
self.helper.layout = Layout( Fieldset( 'first arg is the legend of the fieldset', 'field1', 'field2' ), ButtonHolder( Submit('submit', 'Submit', css_class='button white') ) -
Y el template queda igual {% load crispy_forms_tags %} {%
crispy example_form %} WIN -
Más de crispy forms FormSets Cambiar layouts al vuelo Personalizar...
todo :-) http://django-crispy-forms.readthedocs.org/ -
Nuestro modelo cambia class Persona(models.Model): nombre = models.CharField(...) apellidos =
models.CharField(...) email = models.EmailField(...) -
Ok, hago un syncdb :) ./manage.py syncdb Creating tables ...
Creating table tutsouth_persona Installing custom SQL ... Installing indexes ... Installed 0 object(s) from 0 fixture(s) :-D -
Pero... >>> p = Persona() >>> p.save() Traceback (most recent
call last): ... DatabaseError: table tutsouth_persona has no column named email ;-( -
Soluciones Django ◦ Borrón y cuenta nueva manage flush &&
manage syncdb ◦ Modificar manualmente las tablas manage sql -
Soluciones Django ◦ Borrón y cuenta nueva manage flush &&
manage syncdb ◦ Modificar manualmente las tablas manage sql South -
south South brings migrations to Django applications. • Automatic migration
creation • Database independence • App-savvy • VCS-proof -
Migraciones RAE: Acción y efecto de pasar de un país
a otro para establecerse en él. south: [...] a way of changing your database schema from one version into another [...] -
Migraciones RAE: Acción y efecto de pasar de un país
a otro para establecerse en él. south: [...] a way of changing your database schema from one version into another [...] En ambos sentidos. -
south en dos patadas Migraciones: Primera: manage.py schemamigration APP --initial
Siguientes: manage.py schemamigration APP --auto Aplicar: manage.py migrate [APP] -
Migraciones complicadas ? The field 'Votacion.autor' does not have a
default specified, yet is NOT NULL. ? Since you are making this field non-nullable, you MUST specify a default ? value to use for existing rows. Would you like to: ? 1. Quit now, and add a default to the field in models.py ? 2. Specify a one-off value to use for existing columns now ? Please select a choice: -
Durante el desarrollo Reutilizar la migración: manage.py schemamigration --update --auto
Conflictos manage.py migrate --merge Listar: manage.py migrate --list -
Pruebas :-? • When you’re writing new code, you can
use tests to validate your code works as expected. • When you’re refactoring or modifying old code, you can use tests to ensure your changes haven’ t affected your application’s behavior unexpectedly. -
Pruebas :-? • When you’re writing new code, you can
use tests to validate your code works as expected. • When you’re refactoring or modifying old code, you can use tests to ensure your changes haven’ t affected your application’s behavior unexpectedly. Sí o sí 0:-) -
Métodos disponibles unittest class MyFuncTestCase(unittest.TestCase): def testBasic(self): a = ['larry',
'curly', 'moe'] self.assertEqual(my_func(a, 0), 'larry') doctest def my_func(a_list, idx): """ >>> a = ['larry', 'curly', 'moe'] >>> my_func(a, 0) 'larry' -
unittest Forma parte de Python Cumplir dos condiciones: a. Heredar
de unittest.TestCase b. El método empieza por test Django enriquece con django.utils.unittest -
Ejemplo import unittest class TestDePrueba(unittest.TestCase): def test_prueba_1_1(self): self.assertEquals(1 + 1,
2) def test_con_error(self): self.assertEquals(1 + 1, 2.1, "Intel detected!") -
Modelos Bases de datos de prueba By default the test
databases get their names by prepending test_ to the value of the NAME settings for the databases defined in DATABASES. Ejercicio para el lector: fixtures -
Vistas Test Client simula un navegador from django.test.client import Client
class SimpleTest(unittest.TestCase): def setUp(self): self.client = Client() def test_details(self): response = self.client.get('/customer/details/') self.assertEqual(response.status_code, 200) self.assertEqual(len(response.context['customers']), 5) -
Selenium Utiliza un navegador real 1. Acciones que realiza 2.
Cosas que espera encontrar -
Introducción a Python + Selenium from selenium import webdriver from
selenium.webdriver.common.keys import Keys driver = webdriver.Firefox() driver.get("http://www.python.org") assert "Python" in driver.title elem = driver.find_element_by_name("q") elem.send_keys("selenium") elem.send_keys(Keys.RETURN) assert "Google" in driver.title driver.close() -
Django + Selenium from django.test import LiveServerTestCase from selenium.webdriver.firefox.webdriver import
WebDriver class MySeleniumTests(LiveServerTestCase): @classmethod def setUpClass(cls): cls.selenium = WebDriver() super(MySeleniumTests, cls).setUpClass() @classmethod def tearDownClass(cls): cls.selenium.quit() super(MySeleniumTests, cls).tearDownClass() -
Django + Selenium def test_home(self): self.selenium.get(self.live_server_url) votacion = self.selenium. find_element_by_link_text("Nueva")
self.assertIsNotNone(votacion) votacion.click() self.selenium.save_screenshot('votacion.png') -
Django + Selenium self.selenium.get('%s%s' % (self.live_server_url, '/nueva_votacion/')) titulo_input = self.selenium.find_element_by_id("id_titulo")
titulo_input.send_keys('prueba selenium') autor_input = self.selenium.find_element_by_id("id_autor") autor_input.send_keys('selenium') self.selenium.find_element_by_id('enviar').click() self.selenium.save_screenshot('nueva_votacion.png') titulo = self.selenium.find_element_by_id('titulo') self.assertEquals(titulo.text, 'prueba selenium')