Django tricks (2)

  • 749 views
Uploaded on

Curso de aplicaciones adicionales a tener en cuenta para un proyecto Django: …

Curso de aplicaciones adicionales a tener en cuenta para un proyecto Django:
* django-crispy-forms
* south
* Pruebas y Selenium

More in: Technology
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
No Downloads

Views

Total Views
749
On Slideshare
0
From Embeds
0
Number of Embeds
2

Actions

Shares
Downloads
12
Comments
0
Likes
1

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

Transcript

  • 1. Django TricksJosé Ignacio Galarza @igalarzab Carlos Hernando @chernando
  • 2. django crispy formshttps://github.com/maraujop/django-crispy-forms
  • 3. Crispy forms!{% load crispy_forms_tags %}<form method="post" class="form-horizontal"> {{ my_formset|crispy }}</form>
  • 4. Crispy forms!{% load crispy_forms_tags %}<form method="post" class="form-horizontal"> {{ my_formset|crispy }}</form>El formulario es compatible Twitter Bootstrap
  • 5. Un formulariofrom crispy_forms.helper import FormHelperclass ExampleForm(forms.Form): [...] def __init__(self, *args, **kwargs): self.helper = FormHelper() super(ExampleForm, self).__init__(*args,**kwargs)
  • 6. Personalizamos el formulario[...]self.helper.form_id = id-exampleFormself.helper.form_class = blueFormsself.helper.form_method = postself.helper.form_action = submit_surveyself.helper.add_input(Submit(submit, Submit))
  • 7. Y el template queda{% load crispy_forms_tags %}{% crispy example_form %}
  • 8. Aún más personalizadofrom 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) )
  • 9. Y el template queda igual{% load crispy_forms_tags %}{% crispy example_form %} WIN
  • 10. Más de crispy formsFormSetsCambiar layouts al vueloPersonalizar... todo :-)http://django-crispy-forms.readthedocs.org/
  • 11. south
  • 12. Nuestro modelo cambiaclass Persona(models.Model): nombre = models.CharField(...) apellidos = models.CharField(...)
  • 13. Nuestro modelo cambiaclass Persona(models.Model): nombre = models.CharField(...) apellidos = models.CharField(...) email = models.EmailField(...)
  • 14. Ok, hago un syncdb :)./manage.py syncdbCreating tables ...Creating table tutsouth_personaInstalling custom SQL ...Installing indexes ...Installed 0 object(s) from 0 fixture(s):-D
  • 15. Pero...>>> p = Persona()>>> p.save()Traceback (most recent call last):...DatabaseError: table tutsouth_persona has nocolumn named email;-(
  • 16. syncdb no modifica FAIL
  • 17. SolucionesDjango ○ Borrón y cuenta nueva manage flush && manage syncdb ○ Modificar manualmente las tablas manage sql
  • 18. SolucionesDjango ○ Borrón y cuenta nueva manage flush && manage syncdb ○ Modificar manualmente las tablas manage sqlSouth
  • 19. southSouth brings migrations to Django applications. ● Automatic migration creation ● Database independence ● App-savvy ● VCS-proof
  • 20. MigracionesRAE: 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 [...]
  • 21. MigracionesRAE: 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.
  • 22. south en dos patadasMigraciones: Primera: manage.py schemamigration APP --initial Siguientes: manage.py schemamigration APP --autoAplicar: manage.py migrate [APP]
  • 23. Migraciones complicadas? The field Votacion.autor does not have a default specified, yetis NOT NULL.? Since you are making this field non-nullable, you MUST specifya 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:
  • 24. Durante el desarrolloReutilizar la migración: manage.py schemamigration --update --autoConflictos manage.py migrate --mergeListar: manage.py migrate --list
  • 25. Más cosas interesantesDatamigrationsORM FreezingDependencias...http://south.readthedocs.org/
  • 26. 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.
  • 27. 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:-)
  • 28. Métodos disponiblesunittest 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
  • 29. unittestForma parte de PythonCumplir dos condiciones: a. Heredar de unittest.TestCase b. El método empieza por testDjango enriquece con django.utils.unittest
  • 30. Ejemploimport unittestclass 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!")
  • 31. Pruebas en DjangoPor defecto: APP/tests.pymanage.py test [[[APP].TestCase].test_method]
  • 32. ModelosBases 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
  • 33. VistasTest Client simula un navegadorfrom django.test.client import Clientclass 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)
  • 34. SeleniumUtiliza un navegador real 1. Acciones que realiza 2. Cosas que espera encontrar
  • 35. Introducción a Python + Seleniumfrom selenium import webdriverfrom selenium.webdriver.common.keys import Keysdriver = webdriver.Firefox()driver.get("http://www.python.org")assert "Python" in driver.titleelem = driver.find_element_by_name("q")elem.send_keys("selenium")elem.send_keys(Keys.RETURN)assert "Google" in driver.titledriver.close()
  • 36. Django + Seleniumfrom django.test import LiveServerTestCasefrom selenium.webdriver.firefox.webdriver import WebDriverclass MySeleniumTests(LiveServerTestCase): @classmethod def setUpClass(cls): cls.selenium = WebDriver() super(MySeleniumTests, cls).setUpClass() @classmethod def tearDownClass(cls): cls.selenium.quit() super(MySeleniumTests, cls).tearDownClass()
  • 37. Django + Seleniumdef 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)
  • 38. Django + Seleniumself.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)
  • 39. Finalizando @8-)
  • 40. Más... 33 projects that make developing django apps awesomehttp://elweb.co/programacion/33-projects-that-make-developing-django-apps-awesome/
  • 41. Preguntas :-?
  • 42. Gracias a todos! :-D