Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Django Tricks (2)

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
Tweet

More Decks by Carlos Hernando

Other Decks in Technology

Transcript

  1. Crispy forms! {% load crispy_forms_tags %} <form method="post" class="form-horizontal"> {{

    my_formset|crispy }} </form> El formulario es compatible Twitter Bootstrap
  2. 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)
  3. 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'))
  4. 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') )
  5. Más de crispy forms FormSets Cambiar layouts al vuelo Personalizar...

    todo :-) http://django-crispy-forms.readthedocs.org/
  6. 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
  7. Pero... >>> p = Persona() >>> p.save() Traceback (most recent

    call last): ... DatabaseError: table tutsouth_persona has no column named email ;-(
  8. Soluciones Django ◦ Borrón y cuenta nueva manage flush &&

    manage syncdb ◦ Modificar manualmente las tablas manage sql
  9. Soluciones Django ◦ Borrón y cuenta nueva manage flush &&

    manage syncdb ◦ Modificar manualmente las tablas manage sql South
  10. south South brings migrations to Django applications. • Automatic migration

    creation • Database independence • App-savvy • VCS-proof
  11. 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 [...]
  12. 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.
  13. south en dos patadas Migraciones: Primera: manage.py schemamigration APP --initial

    Siguientes: manage.py schemamigration APP --auto Aplicar: manage.py migrate [APP]
  14. 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:
  15. Durante el desarrollo Reutilizar la migración: manage.py schemamigration --update --auto

    Conflictos manage.py migrate --merge Listar: manage.py migrate --list
  16. 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.
  17. 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:-)
  18. 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'
  19. 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
  20. 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!")
  21. 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
  22. 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)
  23. 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()
  24. 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()
  25. 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')
  26. 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')