Top Banner
Django Tricks José Ignacio Galarza @igalarzab Carlos Hernando @chernando
43

Django tricks (2)

Nov 01, 2014

Download

Technology

Carlos Hernando

Curso de aplicaciones adicionales a tener en cuenta para un proyecto Django:
* django-crispy-forms
* south
* Pruebas y Selenium
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Django tricks (2)

Django TricksJosé Ignacio Galarza @igalarzab

Carlos Hernando @chernando

Page 2: Django tricks (2)

django crispy forms

https://github.com/maraujop/django-crispy-forms

Page 3: Django tricks (2)

Crispy forms!

{% load crispy_forms_tags %}

<form method="post" class="form-horizontal">

{{ my_formset|crispy }}

</form>

Page 4: Django tricks (2)

Crispy forms!

{% load crispy_forms_tags %}

<form method="post" class="form-horizontal">

{{ my_formset|crispy }}

</form>

El formulario es compatible Twitter Bootstrap

Page 5: Django tricks (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)

Page 6: Django tricks (2)

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'))

Page 7: Django tricks (2)

Y el template queda

{% load crispy_forms_tags %}

{% crispy example_form %}

Page 8: Django tricks (2)

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')

)

)

Page 9: Django tricks (2)

Y el template queda igual

{% load crispy_forms_tags %}

{% crispy example_form %}

WIN

Page 10: Django tricks (2)

Más de crispy forms

FormSets

Cambiar layouts al vuelo

Personalizar... todo :-)

http://django-crispy-forms.readthedocs.org/

Page 11: Django tricks (2)

south

Page 12: Django tricks (2)

Nuestro modelo cambia

class Persona(models.Model):

nombre = models.CharField(...)

apellidos = models.CharField(...)

Page 13: Django tricks (2)

Nuestro modelo cambia

class Persona(models.Model):

nombre = models.CharField(...)

apellidos = models.CharField(...)

email = models.EmailField(...)

Page 14: Django tricks (2)

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

Page 15: Django tricks (2)

Pero...

>>> p = Persona()

>>> p.save()

Traceback (most recent call last):

...

DatabaseError: table tutsouth_persona has no column named email

;-(

Page 16: Django tricks (2)

FAILsyncdb no modifica

Page 17: Django tricks (2)

Soluciones

Django

○ Borrón y cuenta nueva

manage flush && manage syncdb

○ Modificar manualmente las tablas

manage sql

Page 18: Django tricks (2)

Soluciones

Django

○ Borrón y cuenta nueva

manage flush && manage syncdb

○ Modificar manualmente las tablas

manage sql

South

Page 19: Django tricks (2)

south

South brings migrations to Django applications.

● Automatic migration creation● Database independence● App-savvy● VCS-proof

Page 20: Django tricks (2)

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 [...]

Page 21: Django tricks (2)

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.

Page 22: Django tricks (2)

south en dos patadas

Migraciones:

Primera:

manage.py schemamigration APP --initial

Siguientes:

manage.py schemamigration APP --auto

Aplicar:

manage.py migrate [APP]

Page 23: Django tricks (2)

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:

Page 24: Django tricks (2)

Durante el desarrollo

Reutilizar la migración:

manage.py schemamigration --update --auto

Conflictos

manage.py migrate --merge

Listar:

manage.py migrate --list

Page 25: Django tricks (2)

Más cosas interesantes

Datamigrations

ORM Freezing

Dependencias

...

http://south.readthedocs.org/

Page 27: Django tricks (2)

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.

Page 28: Django tricks (2)

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:-)

Page 29: Django tricks (2)

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'

"""

Page 30: Django tricks (2)

unittest

Forma parte de Python

Cumplir dos condiciones:a. Heredar de unittest.TestCaseb. El método empieza por test

Django enriquece con django.utils.unittest

Page 31: Django tricks (2)

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!")

Page 32: Django tricks (2)

Pruebas en Django

Por defecto:

APP/tests.py

manage.py test [[[APP].TestCase].test_method]

Page 33: Django tricks (2)

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

Page 34: Django tricks (2)

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)

Page 35: Django tricks (2)

Selenium

Utiliza un navegador real

1. Acciones que realiza2. Cosas que espera encontrar

Page 36: Django tricks (2)

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()

Page 37: Django tricks (2)

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()

Page 38: Django tricks (2)

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')

Page 39: Django tricks (2)

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')

Page 40: Django tricks (2)

Finalizando

@8-)

Page 42: Django tricks (2)

Preguntas

:-?

Page 43: Django tricks (2)

Gracias a todos!

:-D