Notas de lanzamiento de Django 1.1

29 de julio de 2009

Bienvenido a Django 1.1!

Django 1.1 incluye un número de características nuevas novedosas, muchas correcciones de errores y una ruta de actualización fácil desde Django 1.0.

Cambios incompatibles hacia atrás en 1.1

Django tiene una política de estabilidad de la API. Esto significa que, en general, el código que desarrollas contra Django 1.0 debería seguir funcionando sin cambios contra 1.1. Sin embargo, a veces hacemos cambios incompatibles hacia atrás si son necesarios para resolver errores, y hay un puñado de tales (menores) cambios entre Django 1.0 y Django 1.1.

Antes de actualizar a Django 1.1 debes comprobar con cuidado que los siguientes cambios no te afectan, y actualiza tu código si lo hacen.

Cambios en nombres de restricciones

Django 1.1 modifica el método utilizado para generar nombres de restricciones de base de datos de modo que los nombres sean consistentes sin importar la palabra máquina. Este cambio es incompatible con algunos usuarios en sentido inverso.

Si estás utilizando una plataforma de 32 bits, estás exento; no observarás diferencias como resultado de este cambio.

Sin embargo, los usuarios de plataformas de 64 bits pueden experimentar algunos problemas al utilizar el comando de gestión reset. Anteriormente a este cambio, las plataformas de 64 bits generaban un digest de 64 bits y 16 caracteres en el nombre de la restricción; por ejemplo:

ALTER TABLE myapp_sometable ADD CONSTRAINT object_id_refs_id_5e8f10c132091d1e FOREIGN KEY ...

Siguiendo este cambio, todas las plataformas, sin importar el tamaño de palabra, generarán un digest de 32 bits y 8 caracteres en el nombre de la restricción; por ejemplo:

ALTER TABLE myapp_sometable ADD CONSTRAINT object_id_refs_id_32091d1e FOREIGN KEY ...

Como resultado de este cambio, no podrás utilizar el comando reset de gestión en ninguna tabla creada por una máquina de 64 bits. Esto es porque el nuevo nombre generado no coincidirá con el históricamente generado; como resultado, la SQL construida por el comando reset será inválida.

Si necesitas resetear una aplicación que se creó con restricciones de 64 bits, deberás eliminar manualmente la antigua restricción antes de invocar reset.

Los casos de prueba ahora se ejecutan en una transacción

Django 1.1 ejecuta los tests dentro de una transacción, lo que permite una mejor rendimiento de pruebas (consulte mejoras del rendimiento de las pruebas para detalles).

Este cambio es ligeramente incompatible en sentido inverso si existen tests que necesitan probar el comportamiento transaccional, si dependen de suposiciones inválidas sobre el entorno de prueba o si requieren un orden específico de casos de prueba.

En estos casos, se puede utilizar TransactionTestCase en su lugar. Esto es solo una solución rápida para evitar errores de caso de prueba revelados por la nueva aproximación de rollback; a largo plazo, los tests deberían ser reescritos para corregir el caso de prueba.

Removed SetRemoteAddrFromForwardedFor middleware

Para conveniencia, Django 1.0 incluyó una clase de middleware opcional – django.middleware.http.SetRemoteAddrFromForwardedFor – que actualizaba el valor de REMOTE_ADDR en función del encabezado HTTP X-Forwarded-For comúnmente establecido por algunas configuraciones de proxy.

Se ha demostrado que este mecanismo no puede hacerse lo suficientemente confiable para uso general, y que (a pesar de la documentación en contrario) su inclusión en Django puede llevar a los desarrolladores de aplicaciones a asumir que el valor de REMOTE_ADDR es «seguro» o de alguna manera confiable como fuente de autenticación.

Si bien no es directamente una cuestión de seguridad, hemos decidido eliminar esta clase de middleware con la versión Django 1.1. Ha sido reemplazada por una clase que hace nada más que levantar un DeprecationWarning.

Si has estado confiando en esta clase de middleware, el camino de actualización más fácil es:

  • Examina el código tal como existía antes de ser eliminado.

  • Verifica que funciona correctamente con tu proxy upstream, modificándolo para apoyar a tu proxy particular (si es necesario).

  • Introduce tu versión modificada de SetRemoteAddrFromForwardedFor como una pieza de middleware en tu propio proyecto.

Los nombres de los archivos subidos están disponibles más tarde

En Django 1.0, los archivos subidos y almacenados en un campo FileField de un modelo se guardaban en disco antes de que el modelo se guardara en la base de datos. Esto significaba que el nombre real asignado al archivo estaba disponible antes de guardar. Por ejemplo, estaba disponible en un manejo de señal pre-guardar del modelo.

Los textos traducidos son:

Cambios en cómo se guardan los formularios de modelos

En Django 1.1, BaseModelFormSet ahora llama a ModelForm.save().

Esto es incompatibilidad hacia atrás si estabas modificando self.initial en un formulario de modelo en su __init__, o si confiabas en las atributos internos _total_form_count o _initial_form_count de BaseFormSet. Aquellos atributos ahora son métodos públicos.

Se ha corregido el comportamiento de escape del filtro join

El filtro join ya no escapa el valor literal que se pasa para el conectador.

Esto es incompatibilidad hacia atrás en la situación especial de la cadena literal conteniendo uno de los cinco caracteres HTML especiales. Por lo tanto, si estabas escribiendo {{ foo|join:"&" }}, ahora tienes que escribir {{ foo|join:"&" }}.

El comportamiento anterior era un bug y contrario a lo documentado y esperado.

Redirecciones permanentes y la vista genérica redirect_to()

Django 1.1 agrega un argumento permanent al parámetro de la vista django.views.generic.simple.redirect_to(). Esto es técnicamente incompatibilidad hacia atrás si estabas utilizando la vista redirect_to con una clave de formato llamada “permanent”, lo que es muy poco probable.

Los textos traducidos son:

Una característica ha sido marcada como deprecada en Django 1.1:

  • Ya no debes utilizar AdminSite.root() para registrar las vistas administrativas. Es decir, si tu archivo URL contiene la línea:

    (r"^admin/(.*)", admin.site.root),
    

    Debes cambiarla para que lea:

    (r"^admin/", include(admin.site.urls)),
    

Debes comenzar a eliminar el uso de esta característica en tu código inmediatamente.

AdminSite.root lanzará una advertencia PendingDeprecationWarning si se utiliza en Django 1.1. Esta advertencia está oculta por defecto. En Django 1.2, esta advertencia será actualizada a DeprecationWarning, que se mostrará de manera audible. Django 1.3 eliminará completamente AdminSite.root().

Para obtener más detalles sobre nuestras políticas y estrategia de deprecación, consulte Proceso de liberación de Django.

¿Qué hay de nuevo en Django 1.1

Mucho: desde Django 1.0, hemos realizado 1,290 commits de código, corregido 1,206 bugs y agregado aproximadamente 10,000 líneas de documentación.

Las características principales nuevas en Django 1.1 son:

ORM mejoras

Se han agregado dos importantes mejoras al mapeador objeto-relacional (ORM) de Django: soporte para agregados y expresiones de consulta.

Soporte para agregados

Es posible ejecutar ahora consultas SQL de agregación (por ejemplo, COUNT(), MAX(), MIN(), etc.) desde dentro del ORM de Django. Puedes elegir devolver los resultados del agregado directamente o anotar los objetos en un conjunto de consultas (QuerySet) con los resultados de la consulta de agregación.

Esta característica está disponible como nuevos métodos aggregate() y annotate(), y se cubre en detalle en la documentación del ORM de agregación <topics/db/aggregation>.

Expresiones de consulta

Las consultas pueden referirse ahora a otro campo de la consulta y pueden recorrer relaciones para referirse a campos en modelos relacionados. Esto se implementa en el nuevo objeto F; para detalles completos, incluyendo ejemplos, consulta la documentación de expresiones F <django.db.models.F>.

Mejoras del modelo

Se han agregado varias características a la capa de modelos de Django:

«Modelos no administrados»

Ahora puedes controlar si Django gestiona el ciclo de vida de las tablas de la base de datos para un modelo utilizando la opción del modelo managed. Por defecto, esto es True, lo que significa que Django creará las tablas de la base de datos adecuadas en syncdb y las eliminará como parte del comando reset. Es decir, Django gestiona el ciclo de vida de la tabla de la base de datos.

Si estableces esto a False, sin embargo, no se realizarán automáticamente creaciones ni eliminaciones de tablas de la base de datos para este modelo. Esto es útil si el modelo representa una tabla existente o una vista de la base de datos que ha sido creada por algún otro medio.

Para más detalles, consulta la documentación de la opción del modelo managed.

Modelos proxy

Ahora puedes crear modelos proxy: subclases de modelos existentes que solo agregan comportamiento a nivel de Python (en lugar de a nivel de base de datos) y no están representados por una nueva tabla. Es decir, el nuevo modelo es un proxy para algún modelo subyacente, que almacena todos los datos reales.

Puedes encontrar todos los detalles en la documentación de modelos proxy: proxy models documentation. Esta característica es similar a las modelos no administrados en la superficie, por lo que la documentación tiene una explicación de cómo los modelos proxy difieren de los modelos no administrados: how proxy models differ from unmanaged models.

Campos diferidos

En algunas situaciones complejas, tus modelos pueden contener campos que podrían contener una gran cantidad de datos (por ejemplo, campos de texto grandes) o requieren procesamiento costoso para convertirlos en objetos Python. Si sabes que no necesitas esos campos particulares, ahora puedes decirle a Django que no los recupere de la base de datos.

Hacer esto con las nuevas métodos de consulta defer() y only().

Mejoras en pruebas

Algunas mejoras notables se han realizado en el marco de pruebas.

Mejoras del rendimiento de las pruebas

Pruebas escritas utilizando el marco de pruebas de Django se ejecutan ahora con una velocidad dramática aumentada (hasta 10 veces más rápido en muchos casos).

Se logró esto mediante la introducción de pruebas basadas en transacciones: cuando se utiliza django.test.TestCase, tus pruebas ahora se ejecutarán en una transacción que se revertirá cuando esté lista, en lugar de limpiar y volver a poblar la base de datos. Esto conlleva un enorme aumento de velocidad para la mayoría de los tipos de pruebas unitarias. Consulte la documentación sobre TestCase y TransactionTestCase para una descripción completa y algunas notas importantes sobre el soporte de bases de datos.

Mejoras del cliente de prueba

Un par de pequeñas mejoras – pero muy útiles – se han realizado en el cliente de pruebas:

  • La prueba ahora puede seguir automáticamente los redireccionamientos con el argumento follow en las funciones Client.get() y Client.post(). Esto facilita la prueba de vistas que emiten redireccionamientos.

  • Ahora es más fácil acceder al contexto de la plantilla en la respuesta devuelta por el cliente de prueba: simplemente accede al contexto como request.context[key]. La forma antigua, que trata a request.context como una lista de contextos, uno para cada plantilla renderizada en la cadena de herencia, sigue disponible si lo necesitas.

Nuevos características del administrador

Django 1.1 agrega un par de características nuevas y útiles a la interfaz administrativa de Django:

Editable fields on the change list

Ahora puedes hacer que los campos sean editables en las vistas de lista administrativa mediante la nueva opción list_editable del administrador. Estos campos se mostrarán como widgets de formulario en las páginas de lista y podrán ser editados y guardados en bloque.

Admin «acciones»

Puedes definir ahora acciones administrativas que pueden realizar alguna acción a un grupo de modelos en bloque. Los usuarios podrán seleccionar objetos en la página de lista de cambios y luego aplicar estas acciones en bloque a todos los objetos seleccionados.

Django incluye una acción administrativa predefinida para eliminar un grupo de objetos de golpe.

Procesamiento condicional de vistas

Django ahora tiene un mejor soporte para procesamiento condicional de vistas utilizando los encabezados HTTP estándar ETag y Last-Modified. Esto significa que puedes cortocircuitar fácilmente el procesamiento de la vista probando condiciones menos costosas. Para muchas vistas esto puede llevar a una mejora significativa en velocidad y reducción de ancho de banda.

Nombres de URL

Django 1.1 mejora patrones de URL nombrados con la introducción de «espacios de nombres» de URL.

En resumen, esta característica permite que el mismo grupo de URLs, desde la misma aplicación, se incluya en una configuración de URL Django múltiples veces, con prefijios nombrados (potencialmente anidados) que se utilizarán al realizar la resolución inversa. En otras palabras, aplicaciones reutilizables como la interfaz administrativa de Django pueden registrarse varias veces sin conflictos de URL.

Para obtener detalles completos, consulte la documentación sobre la definición de nombres de URL <topics-http-defining-url-namespaces>.

GeoDjango

En Django 1.1, GeoDjango (es decir, django.contrib.gis) tiene varias nuevas características:

  • Soporte para SpatiaLite – una base de datos espacial para SQLite – como backend espacial.

  • Agrupaciones geográficas (Collect, Extent, MakeLine, Union) y expresiones F.

  • Nuevos métodos del conjunto de consultas Geo: collect, geojson y snap_to_grid.

  • Nuevas interfaces de lista para objetos GEOSGeometry.

Para obtener más detalles, consulte la documentación de GeoDjango.

Otras mejoras

Las otras nuevas características y cambios introducidos desde Django 1.0 incluyen:

  • La traducción de los textos es la siguiente:

  • Ahora reverse() y el código que la utiliza (por ejemplo, el template tag {% url %}) funcionan con URLs en el sitio administrativo de Django, siempre y cuando las URL del admin estén configuradas mediante include(admin.site.urls) (enviar solicitudes al admin a la vista admin.site.root sigue funcionando, pero las URLs en el admin no serán «reversibles» cuando se configuren así).

  • La función include() en los módulos de URLconf de Django ahora puede aceptar secuencias de patrones de URL (generados por patterns()) además de nombres de módulo.

  • Ahora las instancias de formularios de Django (la visión general de los formularios) tienen dos métodos adicionales, hidden_fields() y visible_fields(), que devuelven la lista de campos ocultos – es decir, <input type="hidden"> – y visibles en el formulario, respectivamente.

  • La vista genérica redirect_to ahora acepta un argumento de palabra clave adicional permanent. Si permanent es True, la vista emitirá una redirección HTTP permanente (código de estado 301). Si False, la vista emitirá una redirección HTTP temporal (código de estado 302).

  • Se ha agregado un nuevo tipo de búsqueda en la base de datos – week_day – para los campos DateField y DateTimeField. Este tipo de búsqueda acepta un número entre 1 (domingo) y 7 (sábado), y devuelve objetos donde el valor del campo coincide con ese día de la semana. Consulte la lista completa de tipos de búsqueda para detalles.

  • El tag {% for %} en el lenguaje de plantillas de Django ahora acepta una cláusula opcional {% empty %}, que se mostrará cuando {% for %} se le pida a loop sobre una secuencia vacía. Consulte la lista de tags de plantilla integrados para ejemplos de esto.

  • El comando de administración dumpdata ahora acepta nombres de modelo individuales como argumentos, lo que permite exportar solo los datos de modelos particulares.

  • Hay un nuevo filtro de plantilla safeseq, que funciona exactamente igual que el filtro safe para listas, marcando cada elemento en la lista como seguro.

  • Los backends de caché (Cache backends) ahora soportan los comandos incr() y decr() para incrementar y decrementar el valor de una clave de caché. En los backends de caché que admiten incremento/decremento atómico – sobre todo, el backend de memcached – estas operaciones serán atómicas y muy rápidas.

  • Ahora Django puede delegar la autenticación de manera fácil a través del servidor web mediante un nuevo backend de autenticación que admite la variable de entorno estándar REMOTE_USER utilizada para este propósito.

  • Hay una nueva función django.shortcuts.redirect() que facilita emitir redirecciones dadas una objeto, el nombre de una vista o una URL.

  • El backend postgresql_psycopg2 ahora admite la autocomitación nativa de PostgreSQL:ref:<postgresql-notes>. Esta es una característica avanzada específica de PostgreSQL que puede hacer que ciertas aplicaciones con lectura pesadas sean un buen trato más rápidas.

¿Qué sigue?

Tomaremos un breve descanso y luego comenzará el trabajo en Django 1.2 – ¡no hay descanso para los cansados! Si deseas ayudar, la discusión sobre el desarrollo de Django, incluyendo el progreso hacia la versión 1.2, tiene lugar diariamente en la lista de correo django-developers y en el canal IRC #django-dev en irc.libera.chat. ¡Únete a las discusiones!

La documentación en línea de Django también incluye indicaciones sobre cómo contribuir a Django:

Las contribuciones en cualquier nivel – desarrollando código, escribiendo documentación o simplemente triando tickets y ayudando a probar las correcciones de errores propuestas – siempre son bienvenidas y apreciadas.

Eso es todo.