django tricks (2)

Post on 01-Nov-2014

1.292 Views

Category:

Technology

1 Downloads

Preview:

Click to see full reader

DESCRIPTION

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

TRANSCRIPT

Django TricksJosé Ignacio Galarza @igalarzab

Carlos Hernando @chernando

django crispy forms

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

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/

south

Nuestro modelo cambia

class Persona(models.Model):

nombre = models.CharField(...)

apellidos = models.CharField(...)

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

;-(

FAILsyncdb no modifica

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

Más cosas interesantes

Datamigrations

ORM Freezing

Dependencias

...

http://south.readthedocs.org/

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

Pruebas en Django

Por defecto:

APP/tests.py

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

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

Finalizando

@8-)

Preguntas

:-?

Gracias a todos!

:-D

top related