Notas de lanzamiento de Django 1.4

23 de marzo de 2012

Bienvenido a Django 1.4!

Estas notas de lanzamiento cubren las nuevas características , así como algunos cambios incompatibles con la retrocesión que querrás estar al tanto cuando actualices Django 1.3 o versiones anteriores. También hemos eliminado algunas características, que se detallan en nuestro plan de desprecación, y hemos comenzado el proceso de desprecación para algunas características: desprecadas.

Resumen

La característica más grande nueva en Django 1.4 es soporte para zonas horarias cuando se manejan fechas/horas. Cuando está habilitado, esta versión de Django almacenará fechas/horas en UTC, utilizará objetos internos conscientes del tiempo y los traducirá a las zonas horarias locales de los usuarios para su visualización.

Si estás actualizando un proyecto existente a Django 1.4, cambiar al modo consciente del tiempo puede requerir cuidado: el nuevo modo prohíbe algunas conductas bastante descuidadas que se aceptaban anteriormente. Alentamos a cualquier persona que esté actualizando a revisar la guía de migración de zonas horarias y la FAQ de zonas horarias para obtener indicaciones útiles.

Otras características nuevas destacadas en Django 1.4 incluyen:

Donde sea posible, intentamos introducir nuevas características de manera compatible con versiones anteriores según nuestra política de estabilidad de API <misc/api-stability> . Sin embargo, como en las versiones anteriores, Django 1.4 incluye algunas minor changes incompatibles con versiones anteriores ; los usuarios que están actualizando desde versiones anteriores de Django deben leer esa lista cuidadosamente.

Compatibilidad con Python

Django 1.4 ha dejado de soportar Python 2.4. La versión mínima requerida de Python es ahora 2.5. Django se prueba y se soporta en Python 2.5, 2.6 y 2.7.

Esta modificación debería afectar solo a un pequeño número de usuarios de Django, ya que la mayoría de los proveedores de sistemas operativos hoy en día están enviando Python 2.5 o más nuevo como su versión por defecto. Si todavía estás utilizando Python 2.4, sin embargo, necesitarás seguir utilizando Django 1.3 hasta que puedas actualizar. Según nuestra política <internals/release-process>, Django 1.3 continuará recibiendo soporte de seguridad hasta la publicación de Django 1.5.

Django no soporta Python 3.x en este momento. En algún punto antes de la publicación de Django 1.4, planeamos publicar un documento que detalle nuestra cronología completa para deshabilitar Python 2.x y mover a Python 3.x.

¿Qué hay de nuevo en Django 1.4

Soporte de zonas horarias

En versiones anteriores, Django utilizaba fechas/horas «naivas» (es decir, fechas/horas sin una zona horaria asociada), dejando que cada desarrollador interpretara qué significa una fecha/hora dada «realmente». Esto puede causar todo tipo de problemas sutiles relacionados con zonas horarias.

En Django 1.4, ahora puedes cambiar a un modo más correcto y consciente de la zona horaria. En este modo, Django almacena información de fechas/horas en UTC en la base de datos, utiliza objetos datetime conscientes de la zona horaria internamente y los traduce a la zona horaria del usuario en plantillas y formularios. Las razones para utilizar esta característica incluyen:

  • Personalizar el display de fechas y horas para usuarios de todo el mundo.

  • Almacenar fechas/horas en UTC para portabilidad y interoperabilidad de la base de datos. (Este argumento no se aplica a PostgreSQL, porque ya almacena timestamps con información de zona horaria en Django 1.3.)

  • Evitar problemas de corrupción de datos durante las transiciones de DST.

El soporte de zonas horarias está habilitado por defecto en nuevos proyectos creados con startproject. Si deseas utilizar esta característica en un proyecto existente, lee la guía de migración <time-zones-migration-guide>. Si encuentras problemas, hay una ayuda útil en la FAQ.

Soporte para frameworks de pruebas en el navegador

Django 1.4 admite la integración con frameworks de pruebas en el navegador como Selenium. La nueva clase base django.test.LiveServerTestCase te permite probar las interacciones entre los extremos delante y detrás de tu sitio de manera más completa. Consulta la documentación para obtener más detalles y ejemplos concretos.

Estructura de proyecto por defecto actualizada y manage.py

Django 1.4 incluye un nuevo esquema de proyecto por defecto y un archivo manage.py actualizado para el comando de administración startproject. Estas mejoras resuelven algunos problemas con las rutas de importación de Python que causaban dobles importaciones, dificultades al mover desde desarrollo a producción y otros problemas difíciles de depurar en la ruta.

El archivo manage.py anterior llamaba funciones ahora desaconsejadas, por lo que los proyectos que actualicen a Django 1.4 deben actualizar su archivo manage.py. (El antiguo estilo manage.py seguirá funcionando como antes hasta Django 1.6. En 1.5 lanzará una advertencia de desaceleración).

El nuevo archivo recomendado manage.py debería tener este aspecto:

#!/usr/bin/env python
import os, sys

if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "{{ project_name }}.settings")

    from django.core.management import execute_from_command_line

    execute_from_command_line(sys.argv)

Deberías reemplazar {{ project_name }} con el nombre del paquete Python real del proyecto.

Si se importan o se refieren las configuraciones, URLconfs y aplicaciones dentro del proyecto utilizando la prefija de nombre del proyecto (por ejemplo, myproject.settings, ROOT_URLCONF = "myproject.urls", etc.), el nuevo archivo manage.py deberá moverse una carpeta hacia arriba, por lo que estará fuera del paquete de proyecto en lugar de ser adyacente a settings.py y urls.py.

Por ejemplo, con la siguiente estructura:

manage.py
mysite/
    __init__.py
    settings.py
    urls.py
    myapp/
        __init__.py
        models.py

Podrías importar mysite.settings, mysite.urls y mysite.myapp, pero no settings, urls o myapp como módulos de nivel superior.

Cualquier cosa que se importe como un módulo de nivel superior puede colocarse adyacente al nuevo archivo manage.py. Por ejemplo, para desacoplar myapp del módulo de proyecto y importarlo solo como myapp, colócalo fuera del directorio mysite/:

manage.py
myapp/
    __init__.py
    models.py
mysite/
    __init__.py
    settings.py
    urls.py

Si el mismo código se importa de manera inconsistente (algunos lugares con prefijo de proyecto, otros sin él), las importaciones deberán limpiarse cuando se cambie al nuevo archivo manage.py.

Plantillas de proyectos y aplicaciones personalizadas

Los textos traducidos son:

Por ejemplo, Django utilizará el directorio /path/to/my_project_template cuando ejecutes la siguiente orden:

django-admin.py startproject --template=/path/to/my_project_template myproject

También puedes proporcionar un directorio de destino como segundo argumento para ambos startapp y startproject:

django-admin.py startapp myapp /path/to/new/app
django-admin.py startproject myproject /path/to/new/project

Para obtener más información, consulta la documentación de startapp y startproject.

Soporte mejorado WSGI

El comando de administración startproject ahora agrega un módulo wsgi.py al layout del proyecto inicial, que contiene una aplicación WSGI simple que se puede utilizar para la implementación con servidores de aplicaciones WSGI.

El servidor de desarrollo integrado built-in development server ahora admite el uso de una función WSGI definida externamente, lo que permite ejecutar runserver con la misma configuración WSGI utilizada para la implementación. La nueva configuración WSGI_APPLICATION te permite configurar qué función WSGI utiliza runserver.

(El comando de administración runfcgi también envuelve internamente la función WSGI configurada a través de WSGI_APPLICATION.)

Soporte para SELECT FOR UPDATE

Django 1.4 incluye un método QuerySet.select_for_update() del conjunto de consultas, que genera una consulta SQL SELECT ... FOR UPDATE. Esto bloqueará las filas hasta el final de la transacción, lo que significa que otras transacciones no pueden modificar o eliminar filas coincidentes con una consulta FOR UPDATE.

For more details, see the documentation for select_for_update().

Model.objects.bulk_create en el ORM

Esta función te permite crear múltiples objetos de manera más eficiente. Puede dar lugar a aumentos significativos de rendimiento si tienes muchos objetos.

Django utiliza internamente esta función, lo que significa que algunas operaciones (como la configuración de la base de datos para suites de pruebas) han visto un beneficio en términos de rendimiento como resultado.

Consultar los docs de bulk_create() para obtener más información.

Almacenamiento de contraseñas mejorado

El sistema de autenticación de Django (django.contrib.auth) almacena contraseñas utilizando un algoritmo de una sola vía. Django 1.3 utiliza el algoritmo SHA1, pero los aumentos de velocidad de procesamiento y ataques teóricos han revelado que SHA1 no es tan seguro como nos gustaría. Por lo tanto, Django 1.4 introduce un nuevo sistema de almacenamiento de contraseñas: por defecto, Django ahora utiliza el algoritmo PBKDF2 (recomendado por NIST). También puedes elegir fácilmente otro algoritmo (incluido el popular bcrypt). Para obtener más detalles, consulta Cómo Django almacena las contraseñas.

doctype HTML5

Los administradores y otros plantillas incluidas han sido actualizadas para utilizar el doctype HTML5. Aunque Django se asegurará de mantener la compatibilidad con navegadores más antiguos, esta modificación permite utilizar cualquier característica de HTML5 en las páginas de administración sin tener que perder la validez del código HTML o sobreescribir las plantillas proporcionadas para cambiar el doctype.

Filtros de lista en interfaz de administración

Antes de Django 1.4, la aplicación admin permitía especificar filtros de lista de cambios mediante una búsqueda de campo, pero no permitía crear filtros personalizados. Esto ha sido rectificado con un API simple (anteriormente utilizado internamente y conocido como «FilterSpec»). Para obtener más detalles, consulte la documentación para list_filter.

Ordenar múltiple en interfaz de administración

La lista de cambios de administrador ahora admite ordenar por varias columnas. Respetará todos los elementos de la ordering y el ordenar por varias columnas al hacer clic en las cabeceras está diseñado para imitar el comportamiento de GUI de escritorio. También agregamos un método get_ordering() para especificar el ordenamiento dinámicamente (es decir, dependiendo de la solicitud).

Nuevos métodos ModelAdmin

Se agregó un método save_related() a ModelAdmin para facilitar la personalización de cómo se guardan los objetos relacionados en el administrador.

Dos otros nuevos métodos ModelAdmin, get_list_display() y get_list_display_links() permiten una personalización dinámica de campos y enlaces mostrados en la lista de cambios del administrador.

Admin inlines respetan permisos del usuario

Los admin inlines ahora solo permiten acciones para las cuales el usuario tiene permiso. Para relaciones ManyToMany con un modelo intermedio auto-creado (que no tiene sus propios permisos), la permiso de cambio del modelo relacionado determina si el usuario tiene permiso para agregar, cambiar o eliminar relaciones.

Los textos traducidos son:

Django 1.4 agrega tanto una API de bajo nivel para firmar valores como una API de alto nivel para establecer y leer cookies firmadas, uno de los usos más comunes de la firma en aplicaciones web.

Consulte los docs sobre la firma criptográfica para obtener más información.

Nueva guía de formularios

La anterior FormWizard de django.contrib.formtools ha sido reemplazada con una nueva implementación basada en las vistas basadas en clases introducidas en Django 1.3. Cuenta con una API de almacenamiento pluggable y no requiere que el wizard pase campos ocultos para cada paso anterior.

Django 1.4 viene con un backend de almacenamiento basado en sesión y un backend de almacenamiento basado en cookie. El último utiliza las herramientas para firma criptográfica también introducidas en Django 1.4 para almacenar el estado del wizard en las cookies del usuario.

reverse_lazy

Una versión evaluada de forma relajada de reverse() se agregó para permitir el uso de reversos de URL antes de que la configuración de URL del proyecto esté cargada.

Traducir patrones de URL

Django ahora puede buscar una prefijo de idioma en el patrón de URL cuando se utiliza la función auxiliar nueva i18n_patterns(). También es posible definir patrones de URL translatables utilizando django.utils.translation.ugettext_lazy(). Consulte url-internacionalización para obtener más información sobre el prefijo de idioma y cómo internacionalizar los patrones de URL.

Soporte de traducción contextual para {% trans %} y {% blocktrans %}

El soporte de traducción contextual introducido en Django 1.3 a través de la función pgettext se ha extendido a las etiquetas de plantilla trans y blocktrans utilizando el nuevo parámetro context.

URLConf personalizables para SingleObjectMixin

Se agregaron dos nuevas atributos, pk_url_kwarg y slug_url_kwarg, a SingleObjectMixin para permitir la personalización de argumentos de palabra clave en la configuración de URL utilizados por vistas genéricas de objetos individuales.

Etiquetas de asignación

Se agregó una función auxiliar assignment_tag a template.Library para facilitar la creación de etiquetas de plantilla que almacenan datos en una variable de contexto especificada.

*args y **kwargs soporte para funciones auxiliares de etiquetas de plantilla

La función auxiliar de etiqueta de plantilla simple_tag, inclusion_tag y la recientemente introducida assignment_tag pueden aceptar ahora cualquier número de argumentos posicionales o de palabras clave. Por ejemplo:

@register.simple_tag
def my_tag(a, b, *args, **kwargs):
    warning = kwargs["warning"]
    profile = kwargs["profile"]
    ...
    return ...

Luego, en la plantilla, se puede pasar cualquier número de argumentos a la etiqueta de plantilla. Por ejemplo:

{% my_tag 123 "abcd" book.title warning=message|lower profile=user.profile %}

No envolver excepciones con TEMPLATE_DEBUG modo

En versiones anteriores de Django, siempre que el parámetro TEMPLATE_DEBUG estaba establecido en True, cualquier excepción levantada durante la renderización de plantillas (incluso excepciones no relacionadas con la sintaxis de plantilla) se envolvían en TemplateSyntaxError y se re-levantaban. Esto se hacía para proporcionar información detallada sobre la ubicación del código fuente de la plantilla en la página de error 500.

En Django 1.4, las excepciones ya no se envuelven. En su lugar, la excepción original se anota con la información de origen. Esto significa que atrapar excepciones durante la renderización de plantillas es ahora consistente independientemente del valor de TEMPLATE_DEBUG, y no hay necesidad de atrapar y deshacer el TemplateSyntaxError para atrapar otros errores.

Filtro de plantilla truncatechars

Este nuevo filtro corta una cadena a ser no mayor que el número especificado de caracteres. Las cadenas truncadas terminan con una secuencia translatable de puntos suspensivos (»…»). Consulta la documentación para truncatechars para obtener más detalles.

Etiqueta de plantilla static

La aplicación contribuyente staticfiles tiene una nueva etiqueta de plantilla static para referirse a archivos guardados con el almacenamiento de backend STATICFILES_STORAGE. Utiliza el método url del almacenamiento de backend y por lo tanto soporta características avanzadas como servir archivos desde un servicio en la nube.

CachedStaticFilesStorage almacenamiento backend

La aplicación contribuyente staticfiles ahora tiene un almacenamiento django.contrib.staticfiles.storage.CachedStaticFilesStorage que almacena en caché los archivos que guarda (al ejecutar el comando de administración collectstatic) agregando la suma MD5 del contenido del archivo al nombre del archivo. Por ejemplo, el archivo css/styles.css también se guardaría como css/styles.55e7cbb9ba48.css

Protección contra clickjacking simple

Hemos agregado un middleware para proporcionar una protección fácil contra clickjacking utilizando el encabezado X-Frame-Options. No está habilitado por defecto por razones de compatibilidad hacia atrás, pero casi con certeza querrás habilitarlo para ayudar a cerrar la brecha de seguridad en los navegadores que admiten el encabezado.

Mejoras CSRF

Hemos realizado varias mejoras a nuestras características CSRF, incluyendo el decorador ensure_csrf_cookie() , que puede ayudar con sitios AJAX intensivos; protección para solicitudes PUT y DELETE; y las configuraciones CSRF_COOKIE_SECURE y CSRF_COOKIE_PATH, que pueden mejorar la seguridad y utilidad de la protección CSRF. Consulta los docs de CSRF para obtener más información.

Filtrado de informes de errores

Hemos agregado dos decoradores de funciones, sensitive_variables() y sensitive_post_parameters(), para permitir designar las variables locales y parámetros POST que pueden contener información sensible y deben ser filtradas de los informes de errores.

Ahora se filtran sistemáticamente todos los parámetros POST de los informes de errores para ciertas vistas (login, password_reset_confirm, password_change y add_view en django.contrib.auth.views, así como user_change_password en la aplicación administrativa) para prevenir el escape de información sensible como contraseñas de usuarios.

Puedes sobreescribir o personalizar la filtración por defecto escribiendo un filtro personalizado. Para obtener más información, consulta los docs sobre Filtrado de informes de errores.

Extended IPv6 support

Soporte extendido de IPv6

HTML comparisons in tests

Las clases base en django.test ahora tienen algunos ayudantes para comparar HTML sin caer en diferencias irrelevantes en espacios en blanco, citación y ordenamiento de argumentos y cierre de etiquetas autocontenidas. Puedes comparar HTML directamente con las nuevas afirmaciones assertHTMLEqual() y assertHTMLNotEqual(), o usar la bandera html=True con assertContains() y assertNotContains() para probar si la respuesta del cliente contiene un fragmento de HTML dado. Consulta la documentación sobre afirmaciones <assertions> para más información.

Dos nuevos formatos de fecha

Se agregaron dos nuevos formatos date para su uso en filtros de plantilla, etiquetas de plantilla y Format localization:

  • e – el nombre del huso horario del objeto datetime dado

  • o – el número de año ISO 8601

Asegúrate de actualizar tus archivos de formato personalizados <custom-format-files> si contienen e o o en una cadena de formato. Por ejemplo, un archivo de formato de localización español previamente escapaba solo el carácter de formato d:

DATE_FORMAT = r"j \de F \de Y"

Pero ahora también necesita escapar e y o:

DATE_FORMAT = r"j \d\e F \d\e Y"

Para más información, consulta la documentación de fecha.

Características menores

Django 1.4 también incluye varias mejoras menores dignas de mención:

  • Una pila de seguimiento más usable en la página técnica 500. Las filas en la pila de seguimiento que se refieren al código del marco de Django están desdibujadas, mientras que las filas en el código de la aplicación están ligeramente enfatizadas. Esta modificación hace que sea más fácil escanear una pila de seguimiento para problemas en el código de la aplicación.

  • Soporte de tablespaces en PostgreSQL.

  • Nombres personalizados para simple_tag().

  • En la documentación, una página de resumen útil sobre seguridad: visión general de seguridad.

  • La función django.contrib.auth.models.check_password se ha movido al módulo django.contrib.auth.hashers. Importarla desde la ubicación antigua seguirá funcionando, pero debes actualizar tus importaciones.

  • El comando de administración collectstatic ahora tiene una opción --clear para eliminar todos los archivos en el destino antes de copiar o vincular los archivos estáticos.

  • Ahora es posible cargar fijos que contengan referencias hacia adelante cuando se utiliza MySQL con el motor de base de datos InnoDB.

  • Se ha agregado un nuevo manejador de respuesta 403 como 'django.views.defaults.permission_denied'. Puedes establecer tu propio manejador configurando el valor de django.conf.urls.handler403. Consulta la documentación sobre el vista HTTP 403 para obtener más información.

  • El makemessages comando utiliza un nuevo y más preciso analizador léxico, JsLex, para extraer cadenas translatable de archivos JavaScript.

  • La etiqueta de plantilla trans ahora admite un argumento as opcional para poder recuperar una cadena de traducción sin mostrarla pero estableciendo en su lugar una variable de contexto de la plantilla.

  • La etiqueta de plantilla if ahora admite cláusulas {% elif %}.

  • Si tu aplicación Django está detrás de un proxy, es posible que encuentres útil el nuevo parámetro de configuración SECURE_PROXY_SSL_HEADER. Resuelve el problema de que tu proxy «come» el hecho de que la solicitud llegó a través de HTTPS. Pero solo utiliza este parámetro si sabes lo que estás haciendo.

  • Ahora se envía una nueva versión en texto plano del código de estado HTTP 500 de error interno cuando DEBUG es True y Django detecta que la solicitud proviene de código JavaScript. (Se utiliza is_ajax() para esto.)

    Al igual que su homólogo en HTML, contiene una colección de diferentes piezas de información sobre el estado de la aplicación.

    Esto debería hacerlo más fácil de leer cuando se esté depurando la interacción con JavaScript del lado del cliente.

  • Se ha agregado la opción makemessages --no-location.

  • Se ha cambiado el backend de caché locmem para utilizar pickle.HIGHEST_PROTOCOL para una mejor compatibilidad con los otros backends de caché.

  • Se ha agregado soporte en la ORM para generar consultas SELECT que contengan DISTINCT ON.

    La traducción de los textos es la siguiente:

    Para obtener más detalles, consulta la documentación para distinct().

  • La página de inicio del administrador agregará un enlace de restablecimiento de contraseña si incluyes una URL con el nombre 'admin_password_reset' en tu archivo urls.py, por lo que ahora es mucho más fácil conectar la mecánica de restablecimiento de contraseña incorporada y hacerla disponible. Para obtener detalles, consulta Agregar una característica de restablecimiento de contraseña.

  • El backend del motor de bases de datos MySQL puede utilizar ahora la característica de punto de salvamento implementada por MySQL versión 5.0.3 o posterior con el motor de almacenamiento InnoDB.

  • Es posible pasar valores iniciales a las formas de modelo que forman parte tanto de conjuntos de formas de modelo como de conjuntos de formas de modelo inline, devueltos por funciones fabricas modelformset_factory y inlineformset_factory, respectivamente, exactamente igual que con los conjuntos de formas regulares. Sin embargo, los valores iniciales solo se aplican a las formas adicionales, es decir, aquellas que no están ligadas a una instancia de modelo existente.

  • El marco de sitios web puede manejar ahora enlaces HTTPS utilizando la nueva Sitemap.protocol atributo de clase.

  • Una nueva clase django.test.SimpleTestCase que es una subclase de unittest.TestCase y es más ligera que django.test.TestCase y compañía. Puede ser útil en pruebas que no necesitan acceder a la base de datos. Consulta Jerarquía de las clases de pruebas unitarias de Django.

Cambios incompatibles con versiones anteriores en 1.4

La configuración SECRET_KEY es obligatoria

Ejecutar Django con una clave secreta vacía o conocida deshabilita muchas de las protecciones de seguridad de Django y puede provocar vulnerabilidades de ejecución de código remoto. Ninguna sitio web de Django debería nunca ser ejecutado sin una SECRET_KEY.

Los textos traducidos manteniendo todas sus etiquetas intactas son:

django.contrib.admin

La aplicación administrativa incluida django.contrib.admin ha llevado durante mucho tiempo un conjunto estándar de archivos estáticos como JavaScript, imágenes y hojas de estilo. Django 1.3 agregó una nueva aplicación contribuyente django.contrib.staticfiles para manejar tales archivos de manera genérica y definió convenciones para los archivos estáticos incluidos en aplicaciones.

A partir de Django 1.4, los archivos estáticos del administrador también siguen esta convención, para hacer que los archivos sean más fáciles de desplegar. En versiones anteriores de Django, era común definir una configuración ADMIN_MEDIA_PREFIX para apuntar a la URL donde viven los archivos estáticos del administrador en un servidor web. Esta configuración ahora ha sido despreciable y reemplazada por la configuración más general STATIC_URL. Django esperará encontrar los archivos estáticos del administrador bajo la URL <STATIC_URL>/admin/.

Si has utilizado previamente una ruta de URL para ADMIN_MEDIA_PREFIX (por ejemplo, /media/), asegúrate de que STATIC_URL y STATIC_ROOT estén configurados y tu servidor web sirva esos archivos correctamente. El servidor de desarrollo sigue sirviendo los archivos del administrador exactamente como antes. Lee el documento static files howto para obtener más detalles.

Si tu ADMIN_MEDIA_PREFIX está configurado en una dominio específico (por ejemplo, http://media.example.com/admin/), asegúrate de establecer también la configuración de STATIC_URL a la URL correcta – por ejemplo, http://media.example.com/.

Advertencia

Si estás confiando implícitamente en el camino de los archivos estáticos del administrador dentro del código fuente de Django, necesitarás actualizar ese camino. Los archivos se movieron desde django/contrib/admin/media/ a django/contrib/admin/static/admin/.

Navegadores compatibles con el administrador

Django no ha tenido una política clara sobre qué navegadores están soportados por la aplicación del administrador. Nuestra nueva política formaliza las prácticas existentes: los navegadores YUI’s A-grade deberían proporcionar una experiencia de administración completa, con la excepción notable de Internet Explorer 6, que ya no está soportado.

Lanzado hace más de 10 años, IE6 impone muchas limitaciones en el desarrollo web moderno. Las implicaciones prácticas de esta política son que los contribuyentes están libres para mejorar la administración sin considerar estas limitaciones.

Esta es la traducción de los textos:

Se han eliminado las iconos de administración

Como parte de un esfuerzo para mejorar el rendimiento y la usabilidad de la interfaz de ordenación de la lista de cambios de la administración, así como los widgets de «filtro» horizontal y vertical, algunos archivos de iconos se eliminaron y agruparon en dos archivos sprite.

Específicamente: selector-add.gif, selector-addall.gif, selector-remove.gif, selector-removeall.gif, selector_stacked-add.gif y selector_stacked-remove.gif fueron combinados en selector-icons.gif; y arrow-up.gif y arrow-down.gif fueron combinados en sorting-icons.gif.

Si utilizaste esos iconos para personalizar la administración, entonces necesitarás reemplazarlos con tus propios iconos o obtener los archivos de una versión anterior.

Nombres de clases CSS en formularios de administración

Para evitar conflictos con otros nombres comunes de clases CSS (por ejemplo «botón»), agregamos un prefijo («campo-») a todos los nombres de clases CSS generados automáticamente desde los nombres de campos de formulario en las formas principales de administración, formularios inline estacados y celdas de tabulador inline. Debes tener en cuenta ese prefijo en tus hojas de estilo personalizadas o archivos JavaScript si anteriormente utilizaste nombres de campo puros como selectores para estilos personalizados o transformaciones de JavaScript.

Compatibilidad con datos firmados antiguos

Django 1.3 cambió los mecanismos de firma criptográfica utilizados en varios lugares de Django. Si bien Django 1.3 mantuvo fallbacks que aceptarían hashes producidos por los métodos previos, estos fallbacks se eliminaron en Django 1.4.

Por lo tanto, si actualizas directamente a Django 1.4 desde 1.2 o versiones anteriores, es posible que pierdas/invalides ciertas piezas de datos que han sido firmadas criptográficamente utilizando un método antiguo. Para evitar esto, utiliza Django 1.3 durante un período de tiempo para permitir que los datos firmados expiren naturalmente. Las partes afectadas se detallan a continuación, con 1) las consecuencias de ignorar este consejo y 2) el tiempo que debes ejecutar Django 1.3 para que los datos expiren o se vuelvan irrelevantes.

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

    • Consecuencias: El usuario será desconectado y se perderán los datos de sesión.

    • Período de tiempo: Definido por SESSION_COOKIE_AGE.

  • contrib.auth hash de restablecimiento de contraseña

    • Consecuencias: Los enlaces de restablecimiento de contraseña desde antes de la actualización no funcionarán.

    • Período de tiempo: Definido por PASSWORD_RESET_TIMEOUT_DAYS.

Hashes relacionados con formularios: estos tienen una vida útil mucho más corta y son relevantes solo para el breve período en que un usuario podría llenar un formulario generado por la instancia de Django previa a la actualización y tratar de enviarlo a la instancia actualizada:

  • contrib.comments hash de seguridad del formulario

    • Consecuencias: El usuario verá el error de validación «Falló la comprobación de la huella de seguridad».

    • Período de tiempo: La cantidad de tiempo que esperas que los usuarios tarden en llenar formularios de comentarios.

  • FormWizard seguridad hash

    • Consecuencias: El usuario verá un error sobre la forma que ha expirado y será enviado nuevamente a la primera página del asistente, perdiendo los datos ingresados hasta el momento.

    • Período de tiempo: La cantidad de tiempo que esperas que los usuarios tarden en rellenar las formas afectadas.

  • Verificación CSRF

    • Nota: Esto es en realidad un fallback de Django 1.1, no Django 1.2, y solo se aplica si estás actualizando desde la versión 1.1.

    • Consecuencias: El usuario verá un error 403 con cualquier forma POST protegida por CSRF.

    • Período de tiempo: La cantidad de tiempo que esperas que los usuarios tarden en rellenar tales formas.

  • contrib.auth secuencia de actualización del hash de contraseña del usuario

    • Consecuencias: Cada contraseña de usuario se actualizará a un hash de contraseña más fuerte cuando se escriba en la base de datos en 1.4. Esto significa que si actualizas a 1.4 y luego necesitas descender a 1.3, la versión 1.3 no podrá leer las contraseñas actualizadas.

    • Remedio: Establece PASSWORD_HASHERS para utilizar el algoritmo de hash de contraseña original cuando inicialmente actualices a 1.4. Después de confirmar que tu aplicación funciona bien con Django 1.4 y no necesitarás descender a 1.3, habilita los nuevos hashes de contraseñas.

django.contrib.flatpages

A partir de la versión 1.4, el FlatpageFallbackMiddleware solo agrega una barra diagonal final y redirige si la URL resultante se refiere a una página plana existente. Por ejemplo, solicitar /notaflatpageoravalidurl en versiones anteriores redirigía a /notaflatpageoravalidurl/, lo que posteriormente generaba un 404. Solicitar /notaflatpageoravalidurl ahora produce inmediatamente un 404.

Además, los redireccionamientos devueltos por las páginas planas ahora son permanentes (con código de estado 301), para coincidir con el comportamiento del CommonMiddleware.

Serialización de datetime y time

Como consecuencia del soporte a zona horaria, y según la especificación ECMA-262, realizamos cambios en el serializador JSON:

  • Incluye la zona horaria para objetos datetime conscientes de la zona horaria. Lanza una excepción para objetos time conscientes de la zona horaria.

  • Incluye milisegundos para objetos datetime y time. Aún hay pérdida de precisión, porque Python almacena microsegundos (6 dígitos) y JSON solo admite milisegundos (3 dígitos). Sin embargo, es mejor que descartar completamente los microsegundos.

Cambiamos el serializador XML para utilizar el formato ISO8601 para fechas. La letra T se utiliza para separar la parte de fecha de la parte de hora, en lugar de un espacio. La información sobre la zona horaria se incluye en el formato [+-]HH:MM.

Aunque los serializadores ahora utilizan estos nuevos formatos al crear fijaciones, pueden cargar fijaciones que utilicen el antiguo formato.

Cambiamos supports_timezone a False para SQLite

La traducción de los textos es la siguiente:

En el contexto del soporte para husos horarios, esta bandera se cambió a False, y las fechas ahora se almacenan sin información sobre el huso horario en SQLite. Cuando USE_TZ es False, si intentas guardar un objeto datetime consciente del huso horario, Django lanza una excepción.

MySQLdb-específicas excepciones

La backend de MySQL históricamente ha lanzado MySQLdb.OperationalError cuando una consulta desencadenaba una excepción. Lo hemos arreglado, y ahora lanzamos django.db.DatabaseError en su lugar. Si estabas probando por MySQLdb.OperationalError, necesitarás actualizar tus cláusulas except.

La localidad de conexión de la base de datos

Los objetos DatabaseWrapper (es decir, los objetos de conexión referenciados por django.db.connection y django.db.connections["some_alias"]) se utilizaban a nivel de hilo. Ahora son objetos globales para potencialmente compartir entre múltiples hilos. Si bien los objetos de conexión individuales ahora son globales, el diccionario django.db.connections que referencia esos objetos sigue siendo local al hilo. Por lo tanto, si solo utilizas la ORM o DatabaseWrapper.cursor() entonces el comportamiento es igual al anterior. Sin embargo, ten en cuenta que django.db.connection ya no se refiere directamente al objeto de conexión por defecto DatabaseWrapper y ahora es un proxy para acceder a los atributos de ese objeto. Si necesitas acceder al objeto de conexión real DatabaseWrapper, utiliza django.db.connections[DEFAULT_DB_ALIAS] en su lugar.

Como parte de este cambio, todas las conexiones SQLite subyacentes ahora están habilitadas para compartir entre hilos (pasando el atributo check_same_thread=False a pysqlite). Sin embargo, DatabaseWrapper conserva el comportamiento anterior deshabilitando la compartición de hilos por defecto, por lo que esto no afecta ningún código existente que se apoye únicamente en la ORM o en DatabaseWrapper.cursor().

Finalmente, si bien ahora es posible pasar conexiones entre hilos, Django no hace ningún esfuerzo para sincronizar el acceso a la backend subyacente. El comportamiento de concurrencia está definido por la implementación del backend subyacente. Consulta su documentación para obtener más detalles.

La configuración COMMENTS_BANNED_USERS_GROUP

Los comentarios de Django han apoyado históricamente excluir los comentarios de un grupo de usuarios especial, pero nunca hemos documentado la característica adecuadamente y no hemos impuesto la exclusión en otras partes de la aplicación como las etiquetas de plantilla. Para solucionar este problema, eliminamos el código de la clase de alimentación.

Si te basas en esta característica y deseas restaurar el comportamiento antiguo, utiliza un administrador de modelos de comentarios personalizado para excluir el grupo de usuarios, como se muestra a continuación:

from django.conf import settings
from django.contrib.comments.managers import CommentManager


class BanningCommentManager(CommentManager):
    def get_query_set(self):
        qs = super().get_query_set()
        if getattr(settings, "COMMENTS_BANNED_USERS_GROUP", None):
            where = [
                "user_id NOT IN (SELECT user_id FROM auth_user_groups WHERE group_id = %s)"
            ]
            params = [settings.COMMENTS_BANNED_USERS_GROUP]
            qs = qs.extra(where=where, params=params)
        return qs

Guarda este administrador de modelos en tu aplicación personalizada de comentarios (por ejemplo, en my_comments_app/managers.py) y agrega a tu modelo de la aplicación de comentarios personalizada:

from django.db import models
from django.contrib.comments.models import Comment

from my_comments_app.managers import BanningCommentManager


class CommentWithTitle(Comment):
    title = models.CharField(max_length=300)

    objects = BanningCommentManager()

IGNORABLE_404_STARTS y IGNORABLE_404_ENDS configuraciones

Hasta la versión 1.3 de Django, era posible excluir algunas URL del informe de errores 404 de Django agregando prefijos a IGNORABLE_404_STARTS y sufijos a IGNORABLE_404_ENDS.

En Django 1.4, estos dos ajustes son superados por IGNORABLE_404_URLS, que es una lista de expresiones regulares compiladas. Django no enviará un correo electrónico para errores 404 en URLs que coincidan con cualquiera de ellas.

Además, las configuraciones anteriores tenían algunos valores por defecto bastante arbitrarios:

IGNORABLE_404_STARTS = ("/cgi-bin/", "/_vti_bin", "/_vti_inf")
IGNORABLE_404_ENDS = (
    "mail.pl",
    "mailform.pl",
    "mail.cgi",
    "mailform.cgi",
    "favicon.ico",
    ".php",
)

No es papel de Django decidir si tu sitio web tiene una sección legada /cgi-bin/ o un favicon.ico. Como consecuencia, los valores por defecto de IGNORABLE_404_URLS, IGNORABLE_404_STARTS y IGNORABLE_404_ENDS son ahora todos vacíos.

Si has personalizado IGNORABLE_404_STARTS o IGNORABLE_404_ENDS, o si deseas mantener el valor por defecto antiguo, debes agregar las siguientes líneas en tu archivo de configuración:

import re

IGNORABLE_404_URLS = (
    # for each <prefix> in IGNORABLE_404_STARTS
    re.compile(r"^<prefix>"),
    # for each <suffix> in IGNORABLE_404_ENDS
    re.compile(r"<suffix>$"),
)

No olvides escapar caracteres que tienen un significado especial en una expresión regular, como los puntos.

Protección CSRF extendida a PUT y DELETE

Django proporcionaba protección contra CSRF solo para solicitudes POST. Dado que el uso de métodos PUT y DELETE en aplicaciones AJAX está volviéndose más común, ahora protegemos todos los métodos no definidos como seguros por RFC 2616 – es decir, eximimos GET, HEAD, OPTIONS y TRACE, y aplicamos la protección a todo lo demás.

Si estás utilizando métodos PUT o DELETE en aplicaciones AJAX, consulta las instrucciones sobre el uso de AJAX y CSRF.

La vista de restablecimiento de contraseña ahora acepta subject_template_name

La vista password_reset en django.contrib.auth ahora acepta un parámetro subject_template_name, que se pasa a la forma de guardar contraseñas como argumento clave. Si estás utilizando esta vista con una forma personalizada de restablecimiento de contraseña, debes asegurarte de que el método save() de tu forma acepte este argumento clave.

django.core.template_loaders

Esta era una alias para django.template.loader desde 2005, y lo hemos eliminado sin emitir advertencias debido a la longitud de la desactivación. Si tu código todavía referenciaba esto, utiliza django.template.loader en su lugar.

django.db.models.fields.URLField.verify_exists

Esta funcionalidad ha sido eliminada debido a problemas de rendimiento e inseguridad insuperables. Cualquier uso existente de verify_exists debe ser eliminado.

django.core.files.storage.Storage.open

El método open de la clase de almacenamiento base utilizaba un parámetro obscuro mixin que permitía cambiar dinámicamente las clases base del objeto de archivo devuelto. Esto ha sido eliminado. En el raro caso en que dependías del parámetro mixin, puedes lograr lo mismo fácilmente sobrescribiendo el método open, como se muestra a continuación:

from django.core.files import File
from django.core.files.storage import FileSystemStorage


class Spam(File):
    """
    Spam, spam, spam, spam and spam.
    """

    def ham(self):
        return "eggs"


class SpamStorage(FileSystemStorage):
    """
    A custom file storage backend.
    """

    def open(self, name, mode="rb"):
        return Spam(open(self.path(name), mode))

El deserializador YAML ahora utiliza yaml.safe_load

yaml.load puede construir cualquier objeto de Python, lo que puede provocar la ejecución de código arbitrario si procesas un documento YAML que proviene de una fuente no confiable. Esta característica no es necesaria para el deserializador YAML de Django, cuyo uso principal es cargar fijos consistiendo en objetos simples. Aunque los fijos son datos confiados, el deserializador YAML ahora utiliza yaml.safe_load por razones adicionales de seguridad.

Las cookies de sesión ahora tienen la bandera httponly por defecto

Las cookies de sesión incluyen ahora el atributo httponly por defecto para ayudar a reducir el impacto de posibles ataques XSS. Como consecuencia de este cambio, los datos de las cookies de sesión, incluyendo sessionid, ya no son accesibles desde JavaScript en muchos navegadores. Para una compatibilidad hacia atrás estricta, establezca SESSION_COOKIE_HTTPONLY = False en su archivo de configuración.

El filtro urlize ya no escape cada URL

Cuando una URL contiene una secuencia %xx, donde xx son dos dígitos hexadecimales, urlize ahora asume que la URL ya está escapada y no aplica la escapada de URL nuevamente. Esto es incorrecto para las URLs cuya forma no citada contiene una secuencia %xx, pero tales URLs son muy poco probables en el mundo real, porque confundirían a los navegadores.

assertTemplateUsed y assertTemplateNotUsed como administrador de contexto

Ahora es posible comprobar si una plantilla se utilizó dentro de un bloque de código con assertTemplateUsed() y assertTemplateNotUsed(). Y pueden usarse como administradores de contexto:

with self.assertTemplateUsed("index.html"):
    render_to_string("index.html")
with self.assertTemplateNotUsed("base.html"):
    render_to_string("index.html")

Consulte la documentación sobre verificaciones para más información.

Conexiones a la base de datos después de ejecutar el conjunto de pruebas

La traducción de los textos es la siguiente:

Si tu código dependía de que se crearan conexiones a la base de datos de producción después de la ejecución de las pruebas, entonces puedes restaurar el comportamiento anterior sobrescribiendo el método teardown_databases() de DjangoTestRunner.

Salida de manage.py help

manage.py help ahora agrupa los comandos disponibles por aplicación. Si dependías del resultado de este comando – si lo parseabas, por ejemplo – entonces necesitarás actualizar tu código. Para obtener una lista de todos los comandos de gestión disponibles en un script, utiliza manage.py help --commands en su lugar.

Etiqueta de plantilla extends

Anteriormente, la etiqueta extends utilizaba un método defectuoso para analizar argumentos, lo que podría llevar a considerar erróneamente un argumento como una cadena literal cuando no era así. Ahora utiliza parser.compile_filter, al igual que otras etiquetas.

Los detalles internos de la etiqueta no forman parte de la API estable oficial, pero en aras de la transparencia total, la definición de ExtendsNode.__init__ ha cambiado, lo que puede romper cualquier etiqueta personalizada que utilice esta clase.

Cargar algunos fijos incompletos ya no funciona

Anteriormente a 1.4, se insertaba un valor por defecto para objetos de fijo que faltaban una fecha o valor de fecha y hora específico cuando auto_now o auto_now_add estaba configurado para el campo. Esto era algo que no debería haber funcionado, y en 1.4 cargar tales fijos incompletos fallará. Debido a que los fijos son una importación cruda, deben especificar explícitamente todos los valores de campo, independientemente de las opciones de campo en el modelo.

Servidor de desarrollo multihilo

El servidor de desarrollo ahora es multihreaded por defecto. Utiliza la opción runserver --nothreading para deshabilitar el uso de hilos en el servidor de desarrollo:

django-admin.py runserver --nothreading

Los atributos están desactivados en markdown cuando se establece el modo seguro

Antes de Django 1.4, los atributos estaban incluidos en cualquier salida de markdown independientemente del ajuste de la configuración de seguridad del filtro. Con la versión > 2.1 de la biblioteca Python-Markdown, se agregó una opción enable_attributes. Cuando se pasa el argumento seguro al filtro markdown, se establecen tanto safe_mode=True como enable_attributes=False. Si se utiliza una versión de la biblioteca Python-Markdown menor que 2.1, se emite un aviso de que la salida es insegura.

FormMixin get_initial devuelve un diccionario específico de instancia

En Django 1.3, el método get_initial de la clase django.views.generic.edit.FormMixin estaba devolviendo el diccionario initial de la clase. Esto se ha corregido para que devuelva una copia de este diccionario, por lo que las instancias de formulario pueden modificar sus datos iniciales sin afectar la variable de clase.

Características descontinuadas en 1.4

Estilos antiguos de llamada al decorador cache_page

Algunas formas legadas de llamar a cache_page() han sido descontinuadas. Consulte la documentación para saber cómo utilizar correctamente este decorador.

Soporte para versiones de PostgreSQL anteriores a 8.2

Django 1.3 dejó de soportar versiones de PostgreSQL anteriores a 8.0, y sugerimos utilizar una versión más reciente debido a las mejoras de rendimiento y, lo que es más importante, el fin del período de soporte upstream para 8.0 y 8.1 (noviembre de 2010).

Django 1.4 toma esa política más allá y establece la versión mínima de PostgreSQL que oficialmente admite como 8.2.

Las excepciones de solicitud se registran ahora siempre.

Cuando agregamos el soporte de registro en Django en 1.3, el soporte de correo electrónico de errores del administrador fue movido al django.utils.log.AdminEmailHandler, adjuntado a la logger 'django.request'. Para mantener el comportamiento establecido de los correos electrónicos de errores, se llamaba solo a la logger 'django.request' cuando DEBUG era False.

Para aumentar la flexibilidad del registro de errores para solicitudes, ahora se llama a la logger 'django.request' sin importar el valor de DEBUG, y el archivo de configuración predeterminado para nuevos proyectos incluye un filtro separado adjuntado al django.utils.log.AdminEmailHandler para prevenir correos electrónicos de errores del administrador en modo DEBUG:

LOGGING = {
    # ...
    "filters": {
        "require_debug_false": {
            "()": "django.utils.log.RequireDebugFalse",
        }
    },
    "handlers": {
        "mail_admins": {
            "level": "ERROR",
            "filters": ["require_debug_false"],
            "class": "django.utils.log.AdminEmailHandler",
        }
    },
}

Si tu proyecto fue creado antes de esta modificación, tu configuración LOGGING no incluirá este nuevo filtro. Para mantener la compatibilidad hacia atrás, Django detectará que tu configuración de manejo de correo electrónico 'mail_admins' incluye ninguna sección 'filters' y agregará automáticamente este filtro para ti e emitirá un aviso de pendiente de desprecación. Este aviso de desprecación se convertirá en un aviso de desprecación en Django 1.5, y en Django 1.6 el shim de compatibilidad hacia atrás será eliminado por completo.

La existencia de cualquier clave 'filters' bajo el manejo de correo electrónico 'mail_admins' desactivará este shim de compatibilidad hacia atrás y aviso de desprecación.

django.conf.urls.defaults

Hasta Django 1.3, las funciones include(), patterns() y url(), más que handler404 y handler500 estaban ubicadas en un módulo django.conf.urls.defaults.

En Django 1.4, viven en django.conf.urls.

django.contrib.databrowse

Databrowse no ha visto un desarrollo activo durante algún tiempo, y esto no muestra señales de cambiar. Había habido una sugerencia para un proyecto GSOC para integrar la funcionalidad de Databrowse en el administrador, pero no se hizo ningún progreso. Si bien Databrowse ha sido depreciado, una mejora de django.contrib.admin que proporcione un conjunto de características similares todavía es posible.

El código que impulsa a Databrowse está licenciado bajo los mismos términos que Django mismo, por lo que está disponible para ser adoptado por una persona o grupo como proyecto de terceros.

django.core.management.setup_environ

Esta función modificó temporalmente sys.path con el fin de hacer que la carpeta «proyecto» padre sea importable bajo la antigua disposición plana startproject. Esta función ahora está depreciada, ya que sus soluciones de trabajo con rutas ya no son necesarias con la nueva manage.py y la disposición de proyecto por defecto.

Esta función nunca fue documentada ni parte de la API pública, pero se recomendaba ampliamente para su uso en la configuración de un «entorno Django» para un script de usuario. Estos usos deben ser reemplazados estableciendo la variable de entorno DJANGO_SETTINGS_MODULE o utilizando django.conf.settings.configure().

django.core.management.execute_manager

Esta función se utilizaba anteriormente por manage.py para ejecutar un comando de gestión. Es idéntica a django.core.management.execute_from_command_line, excepto que primero llama a setup_environ, que ahora está depreciada. Como resultado, execute_manager también está depreciado; execute_from_command_line se puede utilizar en su lugar. Ninguna de estas funciones está documentada como parte de la API pública, pero un camino de deprecación es necesario debido al uso en archivos existentes manage.py.

Atributos is_safe y needs_autoescape de los filtros de plantilla

Dos banderas, is_safe y needs_autoescape, definen cómo cada filtro de plantilla interactúa con el comportamiento de escape automático de Django. Anteriormente eran atributos de la función del filtro:

@register.filter
def noop(value):
    return value


noop.is_safe = True

Sin embargo, esta técnica causó algunos problemas en combinación con decoradores, especialmente @stringfilter. Ahora las banderas son argumentos de palabra clave de @register.filter:

@register.filter(is_safe=True)
def noop(value):
    return value

See filtros y escape automático para obtener más información.

La expansión de nombres de aplicaciones con comodín en INSTALLED_APPS

Hasta Django 1.3, INSTALLED_APPS aceptaba comodines en los nombres de las aplicaciones, como django.contrib.*. La expansión se realizaba mediante una implementación basada en el sistema de archivos de from <package> import *. Desafortunadamente, esto no puede hacerse con fiabilidad.

Este comportamiento nunca estuvo documentado. Dado que es inpythonico, se eliminó en Django 1.4. Si dependías de él, debes editar tu archivo de configuración para listar todas tus aplicaciones explícitamente.

HttpRequest.raw_post_data renombrado a HttpRequest.body

Esta propiedad tenía el nombre confuso HttpRequest.raw_post_data, pero en realidad proporcionaba el cuerpo de la solicitud HTTP. Se ha renombrado a HttpRequest.body, y HttpRequest.raw_post_data se ha depreciado.

Corrección del bug en django.contrib.sitemaps con implicaciones potenciales para el rendimiento

En versiones anteriores, los objetos Paginator utilizados en las clases de mapas de sitio se almacenaban en caché, lo que podía resultar en mapas de sitio obsoletos. Hemos eliminado la caché, por lo que cada solicitud a un mapa de sitio ahora crea un nuevo objeto Paginator y llama al método items() de la subclase de Sitemap. Dependiendo de lo que haga tu método items(), esto puede tener un impacto negativo en el rendimiento. Para mitigar el impacto en el rendimiento, considera utilizar el framework de caché dentro de la subclase de Sitemap.

Versiones de Python-Markdown anteriores a 2.1

Las versiones de Python-Markdown anteriores a 2.1 no admiten la opción para deshabilitar atributos. Como problema de seguridad, las versiones anteriores de esta biblioteca no serán compatibles con el app contrib de markup en 1.5 bajo un calendario de deprecación acelerado.