Django es el entorno de desarrollo web para perfeccionistas con límites de tiempo

Entradas sobre "aplicaciones":

EveryBlock libera su código fuente

Hace un par de días se ha liberado el código de EveryBlock bajo licencia GPL. EveryBlock ofrece noticias e información local sobre barrios de distintas ciudades de Estados Unidos. Se trata de uno de los sitios web más interesantes que utilizan Django.

El código fuente se puede encontrar dividido en distintos paquetes en el sitio oficial. El código incluye paquetes que trabajan con información geográfica, el sistema de publicación completo de EveryBlock y hasta un paquete de blog y otro de wiki.

Publicado por Antonio Melé el Jueves 2 de Julio de 2009 | 0 comentarios | Categorías: aplicaciones, comunidad, descargas

Migración de esquemas con django-evolution

Las migraciones o evoluciones de esquema son las modificaciones que hacemos a modelos ya creados y que afectan a la base de datos. Cuando sincronizamos por primera vez los modelos de nuestra aplicación mediante syncdb se crean las tablas necesarias para los mismos en la base de datos. Si tras esto realizamos cambios en nuestros modelos tendremos que ejecutar el comando manage.py reset aplicacion para que se borren las tablas correspondientes a nuestra aplicación y vuelvan a crearse nuevas tablas a partir de los nuevos modelos.

El problema se nos plantea cuando tenemos que realizar cambios en modelos que ya estamos utilizando para almacenar datos y por lo tanto no podemos eliminar sus tablas para volver a crearlas. Esto ocurre sobre todo en los entornos de producción. Las soluciones principales son 2: Modificar nuestro modelo y realizar manualmente los cambios equivalentes en sus respectivas tablas de la base de datos ó utilizar alguna herramienta de migración de esquemas como django-evolution, South ó dmigrations.

Vamos a ver cómo usar django-evolution para realizar nuestras migraciones de esquema de una forma sencilla.

Puesta en marcha rápida de django-evolution

  1. Descarga la última versión mediante svn:

    svn checkout http://django-evolution.googlecode.com/svn/trunk/ django-evolution
    
  2. Añade django_evolution al setting INSTALLED_APPS de tu proyecto.

  3. Ejecuta syncdb para que se creen las tablas de django_evolution con la información inicial sobre tus modelos:

    ./manage.py syncdb
    
  4. Modifica los modelos que necesites cambiar

  5. Ejecuta el comando de administración evolve con el parámetro --hint que inspeccionará tus modelos y te mostrará qué migraciones deben hacerse:

    ./manage.py evolve --hint
    
  6. evolve --hint por sí sólo mostrará las migraciones que django-evolution cree que deben hacerse, pero no hará nada. Para realizar las migraciones añade al comando anterior el parámetro --execute si estás de acuerdo con las modificaciones que van a hacerse en el esquema de la base de datos. Se modificarán las tablas de los modelos que han cambiado de acuerdo a las modificaciones que has visto con evolve --hint:

    ./manage.py evolve --hint  --execute
    

Django-evolution a fondo

Es bueno utilizar evolve --hint antes de realizar una migración ya que conviene asegurarse de que los cambios que se han realizado en los modelos han sido detectados correctamente por django-evolution. Al utilizar evolve con el parámetro --sql descubrirás el código SQL que va a ejecutar dicha migración:

./manage.py evolve --hint --sql

django-evolution también permite escribir y almacenar migraciones para que las ejecutemos cuando queramos. Esto es útil cuando estás desarrollando una nueva versión de tu aplicación web: Por un lado en producción tendrás la versión estable de tu aplicación con sus correspondientes modelos. Por otro lado tendrás la nueva versión de desarrollo con modificaciones en tus modelos. Todas las migraciones que realices sobre los modelos en la versión de desarrollo tendrás que realizarlas más adelante sobre los modelos de la versión en producción. Almacenar migraciones te simplificará esta tarea, para ello tendrás que definir mutaciones en un archivo.

Definir mutaciones de modelos

Ya hemos visto que cuando ejecutamos evolve --hint nos aparece la información de las migraciones que van a hacerse en nuestros modelos. Si por ejemplo tenemos un modelo Autor al que añadimos un campo nuevo llamado lugar como el siguiente (con null=True ya que los autores actuales que existan en la base de datos no tendrán lugar definido):

lugar = models.CharField(max_length=100, null=True)

Al ejecutar ./manage.py evolve --hint nos aparecerá la siguiente migración:

#----- Evolution for mi_aplicacion
from django_evolution.mutations import *
from django.db import models

MUTATIONS = [
     AddField('Autor', 'lugar', models.CharField, max_length=100, null=True)
]
#----------------------
Trial evolution successful.
Run './manage.py evolve --execute' to apply evolution.

Se ha detectado que hay que ampliar la tabla de la base de datos con el campo lugar que hemos añadido al modelo Autor. Si nos fijamos, django-evolution nos está dando directamente el código que necesitamos para almacenar la migración, con los import correspondientes y la definición de MUTATIONS (mutaciones de los modelos).

Para guardar nuestras migraciones y poder aplicarlas cuando queramos tenemos que crear un directorio evolutions dentro del directorio de nuestra aplicación y añadirle un archivo __init__.py vacío para que sea interpretado como un módulo de Python. Dentro de evolutions podremos añadir un arhivo .py por cada migración que queramos almacenar. En nuestro caso añadiremos add_lugar.py con el código entre líneas ---- que nos ha dado la ejecución del comando ./manage.py evolve --hint. La estructura de archivos quedará así:

/mi_aplicacion
    /evolutions
        __init__.py
        add_lugar.py
    models.py
    views.py

Y el contenido del archivo add_lugar.py será:

from django_evolution.mutations import *
from django.db import models

MUTATIONS = [
     AddField('Autor', 'lugar', models.CharField, max_length=100, null=True)
]

Por último, ya que generalmente aplicaremos varias migraciones, tenemos que definir el orden en el que deben ejecutarse. Para ello añadimos una lista SEQUENCE a evolutions/__init__.py que contiene el nombre de las migraciones a aplicar por orden. Nuestro __init__.py tendrá:

SEQUENCE = ['add_lugar']

¡Ya hemos almacenado una migración! Ahora no nos hará falta utilizar evolve con el parámetro --hint sino que podremos usarlo directamente: ./manage.py evolve nos mostrará las migraciones que van a hacerse (a partir de las que hemos almacenado y su secuencia). Y ./manage.py evolve --execute las ejecutará.

Publicado por Antonio Melé el Jueves 21 de Mayo de 2009 | 2 comentarios | Categorías: aplicaciones, modelos, pluggables

Convenciones de aplicaciones reusables en Django

Este post es una traducción al español de Django reusable apps conventions, escrito por Eric Holscher. Trata de servir como punto de referencia sobre las mejores prácticas y convenciones en Django. También te pueden interesar las convenciones de proyecto en Django.

¿Qué es una aplicación reusable?

Una aplicación Django reusable es una aplicación que se puede añadir fácilmente a un proyecto y que ofrece una funcionalidad muy específica. Las aplicaciones reusables deberían centrarse en seguir la filosofía Unix de "haz una cosa y hazla bien". Hay más información sobre esto en la charla sobre aplicaciones reusables que dio James Bennett en la Djangocon.

¿Cómo puedo distribuir mi aplicación?

Django debería estar usando el Indice de Paquetes Python (también conocido como Pypi ó Cheese Shop). Hay un tutorial que explica cómo empaquetar y subir tu aplicación a Pypi. Todas las aplicaciones reusables deberían ser subidas a Pypi.

Si subes tu aplicación a Pypi generalmente es una buena idea utilizar el prefijo "django-" en el nombre del proyecto.

Ten también en cuenta que más abajo cuando nos referimos al lugar por omisión para algo como un archivo, esto significa que puedes hacer un directorio con ese mismo nombre como se hace normalmente en Python.

Modelos

URLs

  • Situadas en APP/urls.py (.py ó un directorio)
  • Deben tener un atributo name para que sean reversibles; por ejemplo un nombre siguiendo la nomenclatura APLICACION_MODELO_VISTA, por ejemplo blog_post_detail ó blog_post_list.

Vistas

  • Situadas en APP/views.py (.py ó un directorio)
  • Pueden ser cualquier función Python
  • Las vistas deben proveer valores por defecto fácilmente reemplazables. Por ejemplo:
def register(request, success_url=None,
    form_class=RegistrationForm
    template_name='registration/registration_form.html',
    extra_context=None):

Admin

  • No requerido
  • Situado en APP/admin.py
  • Clases Admin para un MODELO deben ser llamadas MODELOAdmin

Plantillas

  • Situadas en APP/templates/APP/template.html

En un esfuerzo por estandarizar el nombre de bloques en las plantillas de Django se proponen los siguientes bloques para uso común.

  • {% block title %}

    Éste será el bloque en el que definas el título de la página. Preferiblemente tu base.html definirá el nombre de tu sitio web (a lo mejor incluso utilizando el Sites framework) fuera de esta etiqueta para que aparezca en todas las páginas.

  • {% block extra_head %}

    Éste es uno que mucha gente ya está utilizando de una u otra forma. En tu plantilla base tienes cosas en <head> que son utilizadas para todas las demás. Sin embargo, muchas otras páginas necesitan incluir cosas distintas dentro de <head>, como feeds RSS, Javascript, CSS y otras cosas que deben ir en la cabecera. Probablemente necesitarás otros bloques especializados (como el title descrito anteriormente) que se encuentren en otras partes de <head>.

  • {% block body %}

    Esta etiqueta se pondrá englobando toda la sección <body> de la página. Esto te permite crear páginas en tu aplicación que reemplacen la página entera, no sólo el contenido. No la usarás mucho, pero es una etiqueta realmente útil cuando la necesitas. Se intenta mantener el nombre de las etiquetas de forma coherente con las etiquetas HTML cuando es posible.

  • {% block menu %}

    En este bloque deberá estar tu menú. Es donde se debe incluir la navegación general del sitio web, no una sub-navegación interna de una página.

  • {% block content %}

    Este es el lugar para definir el contenido de una página. Preferiblemente será lo que cambie en cada página. No incluirá ninguna navegación del sitio, cabeceras, pies de página, o nada que debiera pertenecer a una plantilla base.

Otros bloques posibles

  • {% block content_title %}

    Este bloque estará donde se encuentre el "título" de un bloque de contenido. También puede incluir algún tipo de navegación entre contenidos u otras cosas similares. Preferiblemente algo que no esté en el contenido de las páginas principales. (Sin embargo a lo mejor debería ir dentro de la etiqueta content y usar otra etiqueta main_content en vez de la etiqueta content propuesta anteriormente.)

  • {% block header %} {% block footer %}

    Para cualquier area de texto en la cabecera ó pie que pueda cambiar según la página.

  • {% block body_id %} {% block body_class %}

    Este bloque se usará para especificar los atributos class ó id de la etiqueta <body> del documento. Es útil especificarlo para el uso de estilos CSS y otras propiedades.

  • {% block [section]_menu %} {% block page_menu %}

    Este bloque sería el opuesto al bloque menu propuesto anteriormente. Debería ser un menú para una sección o página.

Documentación

  • Situada en un directorio docs en el mismo nivel que el directorio APP (claro está que para esto debes tener un directorio por encima de tu aplicación)
  • Puede contener plantillas de referencia

Forms

  • Situados en APP/forms.py

Template tags

  • Situados en APP/templatetags/APP_tags.py

Sintaxis propuesta para template tags

  • as (variable de contexto): Usado para poner una variable en el contexto de una página.
  • for (objeto o app.modelo): Usado para designar un objeto para una acción que debe ejecutar.
  • limit (número): Usado para limitar el resultado a un número concreto de resultados.
  • exclude (objeto o pk): Igual que for pero usado para excluir cosas de ese tipo.

Tests

  • Situados en APP/tests.py (.py ó un directorio)
  • Las fixtures se sitúan en APP/fixtures/fixture.json
  • Generalmente sobreescriben la clase Testcase de Django.

Middleware

  • Situados en APP/middleware.py
  • Los mínimos posibles

Context Processors

  • Situados en APP/context_processors.py

Managers

  • Situados en APP/managers.py

Feeds

  • Situados en APP/feeds.py

Publicado por Antonio Melé el Viernes 1 de Mayo de 2009 | 0 comentarios | Categorías: aplicaciones, convenciones

Ejecutar tareas automáticas con django-chronograph

Django-chronograph es una aplicación que permite programar la ejecución de tareas automáticas de manage.py utilizando cron. Permite especificar las tareas a realizar y el intervalo de tiempo en el que se deben repetir mediante el sitio de administración de Django. Esto es muy útil para automatizar tareas repetitivas de nuestro proyecto como pueden ser enviar un e-mail semanal automático a todos los usuarios ó eliminar diariamente cuentas de usuarios inactivos. Django-chronograph también almacena un listado de logs visible desde el sitio de administración que nos permite comprobar los resultados de las tareas ejecutadas.

Para instalar django-chronograph basta con seguir los siguientes pasos:

  1. Descarga python-dateutil si aún no lo tienes. Es necesario para django-chronograph.

  2. Descarga la última versión de django-chronograph del repositorio mediante svn:

    svn checkout http://django-chronograph.googlecode.com/svn/trunk/ django-chronograph-read-only
    
  3. Añade la aplicación chronograph al setting INSTALLED_APPS y la siguiente URL a tu configuración de URLs en urls.py:

    url(r'^admin/chronograph/job/(?P<pk>\d+)/run/$', 'chronograph.views.job_run', name="admin_chronograph_job_run")
    

    Después ejecuta el comando manage.py syncdb para que se creen las tablas necesarias en la base de datos.

  4. Añade la siguiente línea a tu crontab especificando la ruta en la que se encuentra el archivo manage.py de tu proyecto. Para editar las tareas cron utiliza el comando crontab -e

* * * * * python /path/a/tu/proyecto/manage.py cron

Después podrás gestionar tus tareas automáticas desde el sitio de administración de Django.

django-chronograph en el sitio de administración de Django

Publicado por Antonio Melé el Jueves 9 de Abril de 2009 | 2 comentarios | Categorías: admin, aplicaciones, pluggables