Notas de lanzamiento de Django 1.6

Nota

Dedicado a Malcolm Tredinnick

El 17 de marzo de 2013, el proyecto Django y la comunidad de software libre perdieron un amigo muy querido y desarrollador.

Malcolm era un contribuyente de larga data a Django, miembro de la comunidad modelo, una mente brillante y un amigo. Sus contribuciones a Django —y a muchos otros proyectos de código abierto— son casi imposibles de enumerar. Muchos del equipo de desarrollo central de Django tuvieron sus primeras parches revisados por él; su mentoría nos enriqueció. Su consideración, paciencia y dedicación siempre serán una inspiración para nosotros.

Esta versión de Django es para Malcolm.

– Los desarrolladores de Django

6 de noviembre de 2013

Bienvenido a Django 1.6!

Estas notas de lanzamiento cubren las nuevas características, así como algunas cambios incompatibles con lo anterior que querrás tener en cuenta al actualizar desde Django 1.5 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 <deprecated-features-1.6>.

Compatibilidad con Python

Django 1.6, como Django 1.5, requiere Python 2.6.5 o superior. También se admite oficialmente Python 3. Se recomienda con fuerza la última versión menor para cada serie de Python admitida (2.6.X, 2.7.X, 3.2.X y 3.3.X).

Django 1.6 será la última serie de lanzamientos que apoye a Python 2.6; comenzando con Django 1.7, la versión mínima de Python admitida será 2.7.

Python 3.4 no está soportado, pero se agregará el soporte en Django 1.7.

Nuevas características en Django 1.6

Plantillas de proyecto y aplicación por defecto simplificadas

Las plantillas por defecto utilizadas por startproject y startapp se han simplificado y modernizado. El administrador ahora está habilitado por defecto en nuevos proyectos; el sitios framework ya no lo está. La prevención de clickjacking está ahora activada y la base de datos utiliza SQLite por defecto.

Si las plantillas por defecto no se ajustan a tus gustos, puedes utilizar plantillas de proyecto y aplicación personalizadas.

Gestión de transacciones mejorada

La gestión de transacciones de Django se ha revisado. El autocomit a nivel de base de datos está ahora activado por defecto. Esto hace que la gestión de transacciones sea más explícita y debería mejorar el rendimiento. Las APIs existentes fueron deprecadas, y se introdujeron nuevas APIs, como se describe en los docs de gestión de transacciones.

Conexiones persistentes a la base de datos

Ahora soporta la reutilización de la misma conexión a la base de datos para varias solicitudes. Esto evita el overhead de reestablecer una conexión al comienzo de cada solicitud. Por compatibilidad hacia atrás, esta característica está deshabilitada por defecto. Consulte Conexiones persistentes para detalles.

La descubierta de pruebas en cualquier módulo de prueba

Django 1.6 viene con un nuevo ejecutor de pruebas que permite más flexibilidad en la ubicación de las pruebas. El ejecutor anterior (django.test.simple.DjangoTestSuiteRunner) encontraba pruebas solo en los módulos models.py y tests.py de un paquete Python en INSTALLED_APPS.

El nuevo ejecutor (django.test.runner.DiscoverRunner) utiliza las características de descubierta de pruebas integradas en unittest2 (la versión de unittest en la biblioteca estándar de Python 2.7+ y empaquetada con Django). Con la descubierta de pruebas, las pruebas pueden estar ubicadas en cualquier módulo cuyo nombre coincida con el patrón test*.py.

Además, los etiquetas de prueba proporcionados a ./manage.py test para nominar pruebas específicas que deben ejecutarse deben ser ahora rutas completas de Python (o rutas de directorio), en lugar de pseudo-rutas applabel.TestCase.test_method_name. Esto permite ejecutar pruebas ubicadas en cualquier parte del códigobase, en lugar de solo en INSTALLED_APPS. Para más detalles, consulte Pruebas en Django.

Esta modificación es incompatibilidad hacia atrás; consulte las notas de incompatibilidad hacia atrás <new-test-runner>.

Agregación consciente de zona horaria

El soporte para zonas horarias introducido en Django 1.4 no funcionaba bien con QuerySet.dates(): la agregación siempre se realizaba en UTC. Esta limitación fue levantada en Django 1.6. Utilice QuerySet.datetimes() para realizar agregaciones conscientes de zona horaria en un DateTimeField.

Soporte para puntos de control en SQLite

Django 1.6 agrega soporte para puntos de control en SQLite, con algunas limitaciones.

BinaryField campo del modelo

Se ha agregado un nuevo django.db.models.BinaryField campo del modelo que permite almacenar datos binarios crudos en la base de datos.

Widgets de formularios GeoDjango

GeoDjango ahora proporciona campos y widgets de formularios para sus campos geo-especializados. Están basados por defecto en OpenLayers, pero se pueden personalizar para utilizar cualquier otra biblioteca JS.

Comando administrativo check agregado para verificar la compatibilidad

Se ha agregado el comando administrativo check, que te permite verificar si tu configuración actual (actualmente orientada a settings) es compatible con la versión actual de Django.

Cambio en el algoritmo del método save()

El método Model.save() ahora intenta actualizar directamente la base de datos si la instancia tiene un valor de clave primaria. Anteriormente se realizaba una consulta para determinar si era necesario realizar una actualización o una inserción. El nuevo algoritmo necesita solo una consulta para actualizar una fila existente, mientras que el antiguo algoritmo necesitaba dos. Consulta Model.save() para obtener más detalles.

En algunos casos raros la base de datos no informa que se encontró una fila coincidente cuando se realiza una actualización. Un ejemplo es el trigger ON UPDATE de PostgreSQL, que devuelve NULL. En tales casos es posible establecer la bandera django.db.models.Options.select_on_save para forzar a guardar utilizar el antiguo algoritmo.

Características menores

  • Los backends de autenticación pueden levantar una excepción PermissionDenied para fallar inmediatamente en la cadena de autenticación.

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

  • Ahora, assertQuerysetEqual() verifica si el orden está indefinido y lanza un ValueError si encuentra un orden indefinido. El orden se considera indefinido si la consulta dada no está ordenada y hay más de un valor ordenado para comparar.

  • Se ha agregado earliest() para simetría con latest().

  • Además de los lookups year, month y day, el ORM ahora admite los lookups hour, minute y second.

  • Django ahora envuelve todas las excepciones PEP 249.

  • Los widgets predeterminados para EmailField, URLField, IntegerField, FloatField y DecimalField utilizan los nuevos atributos de tipo disponibles en HTML5 (type=”email”, type=”url”, type=”number”). Ten en cuenta que debido a la falta de soporte errático del tipo de entrada number con números locales en los navegadores actuales, Django solo lo utiliza cuando los campos numéricos no están localizados.

  • El argumento number para traducciones plurales perezosas se puede proporcionar durante la traducción en lugar de durante el tiempo de definición.

  • Para comandos de gestión personalizados: La verificación de la presencia de configuraciones válidas en los comandos que lo solicitan mediante la opción interna BaseCommand.can_import_settings se realiza ahora independientemente del manejo de la zona horaria que debería estar activa durante la ejecución del comando. Esta última puede influir ahora mediante la nueva opción interna BaseCommand.leave_locale_alone. Consulte comandos de gestión y zonas horarias para obtener más detalles.

  • La propiedad success_url de DeletionMixin se interpola ahora con el __dict__ del objeto object.

  • HttpResponseRedirect y HttpResponsePermanentRedirect proporcionan ahora un atributo url (equivalente a la URL a la que redirige la respuesta).

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

  • Se ha agregado la clase SuccessMessageMixin, que proporciona un atributo success_message para las clases basadas en FormView.

  • Se han agregado las opciones django.db.models.ForeignKey.db_constraint y django.db.models.ManyToManyField.db_constraint.

  • La biblioteca jQuery incorporada en la administración se ha actualizado a la versión 1.9.1.

  • Los feeds de sindicación (django.contrib.syndication) pueden pasar contexto adicional a las plantillas de feed utilizando una nueva llamada al callback Feed.get_context_data().

  • Las columnas de la lista administrativa tienen un clase column-<field_name> en el HTML, por lo que se puede personalizar con CSS el encabezado de las columnas, p. ej., para establecer el ancho de una columna.

  • El nivel de aislamiento (isolation level) se puede personalizar bajo PostgreSQL.

  • La etiqueta de plantilla blocktrans ahora respeta TEMPLATE_STRING_IF_INVALID para variables no presentes en el contexto, exactamente como otros constructos de plantillas.

  • Los objetos SimpleLazyObjects ahora presentan representaciones más útiles en situaciones de depuración del shell.

  • El campo GeometryField genérico ahora es editable con el widget OpenLayers en la administración.

  • La documentación contiene un listado de verificación de despliegue.

  • El comando diffsettings obtuvo una opción --all.

  • Ahora django.forms.fields.Field.__init__ llama a super(), lo que permite que las mezclas de campos implementen métodos __init__() que se llamarán con confiabilidad.

  • Se agregó el parámetro validate_max a BaseFormSet y formset_factory(), así como versiones de modelo e inline del mismo. Se aclaró el comportamiento de la validación para formularios con max_num. Se documentó el comportamiento previamente no documentado que protegía contra ataques de agotamiento de memoria, y se cambió la limitación no documentada de 1000 o max_num formas a siempre 1000 más que max_num.

  • Se agregó BCryptSHA256PasswordHasher para resolver el problema de truncado de contraseña con bcrypt.

  • Pillow es ahora la biblioteca preferida de manipulación de imágenes para usar con Django. PIL está pendiente de despreciable (apoyo a ser eliminado en Django 1.8). Para actualizar, debes primero desinstalar PIL, luego instalar Pillow.

  • ModelForm acepta varias nuevas opciones Meta.

    • Los campos incluidos en la lista localized_fields se localizarán (estableciendo localize en el campo de formulario).

    • Las opciones labels, help_texts y error_messages pueden usarse para personalizar los campos predeterminados, consulte Sobreescribir los campos por defecto para detalles.

  • El argumento choices a los campos de modelo ahora acepta un iterable de iterables en lugar de requerir un iterable de listas o tuplas.

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

  • Al proporcionar la URL de la página siguiente para `django.contrib.auth.views.logout(), `django.contrib.auth.views.password_reset(), `django.contrib.auth.views.password_reset_confirm(), y `django.contrib.auth.views.password_change(), ahora puedes pasar nombres de URL y se resolverán.

  • La nueva opción dumpdata –pks especifica las claves primarias de los objetos a exportar. Esta opción solo puede usarse con un modelo.

  • Se han agregado métodos QuerySet: first() y last(), que son métodos de conveniencia que devuelven el primer o último objeto que coincida con los filtros. Devuelve None si no hay objetos que coincidan.

  • Ahora se admiten tanto la clase ~django.views.generic.base.View como la clase ~django.views.generic.base.RedirectView para el método HTTP PATCH.

  • El campo GenericForeignKey ahora admite un argumento opcional for_concrete_model, que cuando está establecido en False permite al campo referenciar modelos proxy. El valor por defecto es True para mantener el comportamiento antiguo.

  • La clase ~django.middleware.locale.LocaleMiddleware ahora almacena el idioma activo en la sesión si no está presente allí. Esto previene la pérdida de configuración de idiomas después del vaciado de la sesión, por ejemplo, al cerrar sesión.

  • Se ha diferenciado la excepción ~django.core.exceptions.SuspiciousOperation en varias subclases, y cada una se registrará en un logger con nombre correspondiente bajo la jerarquía de logging django.security. Además, se utiliza el mecanismo handler400 y la vista predeterminada siempre que una SuspiciousOperation llegue al manipulador WSGI para devolver un HttpResponseBadRequest.

  • La excepción ~django.db.models.Model.DoesNotExist ahora incluye un mensaje indicando el nombre del atributo utilizado en la búsqueda.

  • El método get_or_create() ya no requiere al menos un argumento de palabra clave.

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

  • La lista de campos relacionados agregada a una QuerySet por select_related() se puede eliminar utilizando select_related(None).

  • Las get_extra() y get_max_num() métodos en la clase InlineModelAdmin pueden sobreescribirse para personalizar el número extra y máximo de formularios en línea.

  • Los formularios ahora tienen un método total_error_count().

  • Los campos de la clase ModelForm pueden sobreescribir mensajes de error definidos en los campos del modelo utilizando el argumento error_messages del constructor de un Field. Para aprovechar esta nueva característica con tus campos personalizados, consulte la recomendación actualizada para levantar una ValidationError.

  • La clase ModelAdmin ahora conserva los filtros en la vista de lista después de crear, editar o eliminar un objeto. Es posible restaurar el comportamiento anterior de eliminar los filtros estableciendo la propiedad preserve_filters a False.

  • Se agregó el método FormMixin.get_prefix (que devuelve por defecto FormMixin.prefix) para permitir personalizar la prefix del formulario.

  • Las consultas crudas (Manager.raw() o cursor.execute()) pueden utilizar ahora el estilo de parámetros «pyformat», donde los placeholders en la consulta se dan como '%(name)s' y los parámetros se pasan como un diccionario en lugar de una lista (excepto en SQLite). Esto ha sido posible durante mucho tiempo (aunque no oficialmente soportado) en MySQL y PostgreSQL, y ahora también está disponible en Oracle.

  • Se incrementó el recuento de iteraciones por defecto para el hasheador de contraseña PBKDF2 en un 20%. Este cambio compatible con versiones anteriores no afectará a las contraseñas existentes o a los usuarios que hayan sobrescrito django.contrib.auth.hashers.PBKDF2PasswordHasher para cambiar el valor por defecto. Las contraseñas se actualizarán según sea necesario para utilizar el nuevo recuento de iteraciones.

Cambios incompatibles con versiones anteriores en 1.6

Advertencia

Además de los cambios descritos en esta sección, asegúrate de revisar el plan de desprecación para cualquier característica que haya sido eliminada. Si no has actualizado tu código dentro del plazo de desprecación para una determinada característica, su eliminación puede aparecer como un cambio incompatible con el pasado.

Nuevo modelo de gestión de transacciones

Cambios de comportamiento

El autocommit a nivel de base de datos está habilitado por defecto en Django 1.6. Si bien esto no cambia el espíritu general de la gestión de transacciones de Django, hay algunas incompatibilidades con el pasado.

Puntos de salvaguarda y assertNumQueries

Los cambios en la gestión de transacciones pueden dar lugar a declaraciones adicionales para crear, liberar o anular puntos de salvaguarda. Esto es más probable que suceda con SQLite, ya que no soportaba puntos de salvaguarda hasta esta versión.

Si los tests utilizando assertNumQueries() fallan debido a un número mayor de consultas que el esperado, verifica si las consultas adicionales están relacionadas con puntos de salvaguarda y ajusta el número de consultas esperadas en consecuencia.

Opción de autocommit para PostgreSQL

En versiones anteriores, el autocommit a nivel de base de datos solo era una opción para PostgreSQL y estaba deshabilitado por defecto. Esta opción ahora se ignora y puede eliminarse.

Nueva ejecución de tests

Para mantener una mayor consistencia con el módulo unittest de Python, el nuevo ejecutor de pruebas (django.test.runner.DiscoverRunner) no admite automáticamente algunos tipos de pruebas que eran admitidos por el ejecutor anterior:

  • Las pruebas en los archivos models.py y tests/__init__.py ya no serán encontradas ni ejecutadas. Mueve las pruebas a un archivo cuyo nombre comience con test.

  • Los doctests ya no se descubrirán automáticamente. Para integrar los doctests en tu suite de pruebas, sigue las recomendaciones del documento de Python <doctest-unittest-api>.

Django incluye una versión modificada del módulo doctest de la biblioteca estándar de Python (en django.test._doctest) y algunas utilidades adicionales para doctests. Estas utilidades están desaconsejadas y se eliminarán en Django 1.8; las suites de pruebas con doctests deben ser actualizadas para funcionar con el módulo doctest estándar (o convertirse en pruebas compatibles con unittest).

Si deseas retrasar la actualización de tu suite de pruebas, puedes establecer tu configuración TEST_RUNNER a django.test.simple.DjangoTestSuiteRunner para restaurar completamente el comportamiento antiguo del ejecutor. DjangoTestSuiteRunner está desaconsejado pero no se eliminará de Django hasta la versión 1.8.

Eliminación del ejecutor personalizado de pruebas GeoDjango django.contrib.gis.tests.GeoDjangoTestSuiteRunner

Esto es para desarrolladores que trabajan en la aplicación GeoDjango misma y relacionado con el item anterior sobre cambios en los ejecutores de pruebas:

El ejecutor de pruebas django.contrib.gis.tests.GeoDjangoTestSuiteRunner ha sido eliminado y la configuración de ejecución de pruebas independiente implementada por él ya no está soportada. Para ejecutar las pruebas GeoDjango simplemente utiliza el nuevo DiscoverRunner y especifica la aplicación django.contrib.gis.

Modelos de usuarios personalizados en pruebas

La introducción del nuevo ejecutor de pruebas ha cambiado ligeramente la forma en que se importan los modelos de prueba. Como resultado, cualquier prueba que sobreescriba AUTH_USER_MODEL para probar el comportamiento con uno de los modelos de usuario de prueba de Django ( django.contrib.auth.tests.custom_user.CustomUser y django.contrib.auth.tests.custom_user.ExtensionUser) debe importar explícitamente el modelo de usuario en su módulo de prueba:

from django.contrib.auth.tests.custom_user import CustomUser


@override_settings(AUTH_USER_MODEL="auth.CustomUser")
class CustomUserFeatureTests(TestCase):
    def test_something(self):
        # Test code here
        ...

Esta es la traducción de los textos:

ImproperlyConfigured: AUTH_USER_MODEL refers to model 'auth.CustomUser' that has not been installed

Consultas day, month y week_day conscientes del huso horario

Django 1.6 introduce el soporte para husos horarios en las consultas day, month y week_day cuando la configuración USE_TZ es True. Estas consultas se realizaban anteriormente en UTC sin importar el huso horario actual.

Esto requiere las definiciones de husos horarios en la base de datos . Si estás utilizando SQLite, debes instalar pytz. Si estás utilizando MySQL, debes instalar pytz y cargar las tablas de husos horarios con mysql_tzinfo_to_sql.

Adición de QuerySet.datetimes()

Cuando el soporte para husos horarios agregado en Django 1.4 estaba activo, QuerySet.dates() las consultas devolvían resultados inesperados porque la agrupación se realizaba en UTC. Para solucionar esto, Django 1.6 introduce una nueva API, QuerySet.datetimes(). Esto requiere unos pocos cambios en tu código.

QuerySet.dates() devuelve objetos date

QuerySet.dates() ahora devuelve una lista de date. Anteriormente devolvía una lista de datetime.

QuerySet.datetimes() devuelve una lista de datetime.

QuerySet.dates() ya no es usable en DateTimeField

QuerySet.dates() lanza un error si se utiliza en DateTimeField cuando el soporte de zona horaria está activo. Utiliza QuerySet.datetimes() en su lugar.

date_hierarchy requiere definiciones de zona horaria

La característica date_hierarchy del admin ahora depende de QuerySet.datetimes() cuando se utiliza en un DateTimeField.

Esto requiere definiciones de zona horaria en la base de datos cuando USE_TZ es True. Aprende más.

date_list en vistas genéricas requiere definiciones de zona horaria

Por la misma razón, acceder a date_list en el contexto de una vista genérica basada en fechas requiere definiciones de zona horaria en la base de datos cuando la vista está basada en un DateTimeField y USE_TZ es True. Aprende más.

Las nuevas consultas pueden chocar con campos del modelo

Django 1.6 introduce las consultas hour, minute y second en DateTimeField. Si tenías campos de modelo llamados hour, minute o second, las nuevas consultas colisionarán con tus nombres de campo. Añade una consulta explícita exact si esto es un problema.

BooleanField ya no tiene el valor por defecto False

Cuando un BooleanField no tiene un valor de default explícito, el valor implícito por defecto es None. En versiones anteriores de Django era False, pero eso no representaba con precisión la falta de valor.

Los textos traducidos son:

Traducciones y comentarios en plantillas

Extracción de traducciones después de los comentarios

La extracción de literales translatables de las plantillas con la orden makemessages detecta ahora correctamente los constructos i18n cuando se encuentran después de un comentario {# / #}-tipo en la misma línea. Por ejemplo:

{# A comment #}{% trans "This literal was incorrectly ignored. Not anymore" %}

Ubicación de comentarios del traductor

Los Comentarios para traductores en plantillas especificados con {# / #} deben estar al final de una línea. Si no lo están, los comentarios se ignoran y makemessages generará un aviso. Por ejemplo:

{# Translators: This is ignored #}{% trans "Translate me" %}
{{ title }}{# Translators: Extracted and associated with 'Welcome' below #}
<h1>{% trans "Welcome" %}</h1>

Citar en reverse()

Cuando se invertían las URL, Django no aplicaba django.utils.http.urlquote a los argumentos antes de interpolarlos en patrones de URL. Este bug está resuelto en Django 1.6. Si trabajaste alrededor de este bug aplicando la citación de URL antes de pasar los argumentos a reverse(), esto puede resultar en doble-citación. Si esto sucede, simplemente elimina la citación de URL de tu código. También tendrás que reemplazar los caracteres especiales en las URLs utilizadas en assertRedirects() con sus versiones codificadas.

Almacenamiento de direcciones IP en la aplicación de comentarios

La aplicación de comentarios ahora utiliza un GenericIPAddressField para almacenar las direcciones IP de los comentaristas, para apoyar comentarios enviados desde direcciones IPv6. Hasta ahora, las almacenaba en un IPAddressField, que solo está diseñado para soportar IPv4. Cuando se guarda un comentario hecho desde una dirección IPv6, la dirección se truncaría silenciosamente en bases de datos MySQL y lanzaría una excepción en Oracle. Debes cambiar el tipo de columna en tu base de datos para aprovechar esta mejora.

Para MySQL, ejecuta esta consulta en la base de datos de tu proyecto:

ALTER TABLE django_comments MODIFY ip_address VARCHAR(39);

Para Oracle, ejecuta esta consulta:

ALTER TABLE DJANGO_COMMENTS MODIFY (ip_address VARCHAR2(39));

Si no aplicas este cambio, el comportamiento sigue siendo el mismo: en MySQL, las direcciones IPv6 se truncan silenciosamente; en Oracle, se genera una excepción. No es necesario realizar ningún cambio en la base de datos para SQLite o PostgreSQL.

Líterales porcentuales en consultas cursor.execute

Cuando estás ejecutando consultas SQL brutas a través del método cursor.execute , se ha unificado la regla sobre el doble de líterales porcentuales (%) dentro de la consulta. El comportamiento pasado dependía del backend de base de datos. Ahora, en todos los backends, solo debes duplicar los caracteres porcentuales literales si también estás proporcionando parámetros de reemplazo. Por ejemplo:

# No parameters, no percent doubling
cursor.execute("SELECT foo FROM bar WHERE baz = '30%'")

# Parameters passed, non-placeholders have to be doubled
cursor.execute("SELECT foo FROM bar WHERE baz = '30%%' and id = %s", [self.id])

Los usuarios de SQLite deben comprobar y actualizar tales consultas.

Texto de ayuda de campos de formulario de modelo para campos ManyToManyField

La representación en HTML de los campos de formulario de modelo correspondientes a los campos de modelo ManyToManyField utilizados para obtener la oración con texto fijo:

Hold down «Control», or «Command» on a Mac, to select more than one.

( o su traducción al idioma activo) impuesta como leyenda de ayuda mostrada junto a ellos si no se especificaron ni el atributo model ni el atributo help_text de la forma (o esta cadena se agregó a cualquier help_text que se proporcionó).

Since este evento ocurrió en la capa del modelo, no había forma de evitar que el texto apareciera en casos donde no era aplicable, como campos de formulario que implementan interacciones con el usuario que no involucran un teclado y/o un ratón.

A partir de Django 1.6, como una disposición provisional de compatibilidad hacia atrás, la lógica para agregar la oración «Sosteniendo…» se ha movido a la capa del campo de formulario del modelo y se ha modificado para agregar el texto solo cuando el widget asociado es SelectMultiple o subclases seleccionadas.

El cambio puede afectarte de manera incompatible hacia atrás si empleas campos de formulario personalizados y/o widgets para los campos de modelo ManyToManyField cuyos UIs dependen de la provisión automática de la mencionada oración con texto duro. Estas implementaciones de campos de formulario necesitan adaptarse al nuevo escenario proporcionando su propia gestión del atributo help_text.

Las aplicaciones que utilizan las facilidades de formularios de modelo de Django :doc:` </topics/forms/modelforms>` junto con los campos y widgets de formulario integrados de Django :doc:` </ref/forms/fields>` y :doc:` </ref/forms/widgets>` no están afectadas pero necesitan estar al tanto de lo descrito en Manipulación del texto de ayuda de los campos de formulario de modelos para campos ManyToManyField a continuación.

Iteración del conjunto de consultas

La iteración del conjunto de consultas se cambió para convertir inmediatamente todas las filas fetcheadas a objetos Model. En Django 1.5 y versiones anteriores, las filas fetcheadas se convirtieron en objetos Model en lotes de 100.

El código existente funcionará, pero la cantidad de filas convertidas a objetos puede cambiar en ciertos casos de uso. Tales usos incluyen bucles parciales sobre un conjunto de consultas o cualquier uso que termine haciendo __bool__ o __contains__.

Notablemente, la mayoría de los motores de bases de datos ya fetcheaban todas las filas en una sola operación en 1.5.

Aún es posible convertir las filas fetcheadas a objetos de manera perezosa utilizando el método iterator().

El método BoundField.label_tag ahora incluye la sufijo de etiqueta del formulario label_suffix

Este es el resultado de la traducción:

Si manualmente renderizas label_tag en tus plantillas:

{{ form.my_field.label_tag }}: {{ form.my_field }}

deberás eliminar el signo de dos puntos (o cualquier otro separador que estés utilizando) para evitar duplicarlos al actualizar a Django 1.6. La siguiente plantilla en Django 1.6 se renderizará exactamente igual que la plantilla anterior en Django 1.5, excepto por el hecho de que el signo de dos puntos aparecerá dentro del elemento <label>.

{{ form.my_field.label_tag }} {{ form.my_field }}

se renderizará algo como:

<label for="id_my_field">My Field:</label> <input id="id_my_field" type="text" name="my_field" />

Si deseas mantener el comportamiento actual de renderizar label_tag sin la label_suffix, instancia la forma con label_suffix=''. También puedes personalizar la label_suffix en una base por campo utilizando el nuevo parámetro label_suffix en label_tag().

Vistas de administración _changelist_filters parámetro GET

Para lograr preservar y restaurar los filtros de la vista de lista, las vistas de administración ahora pasan el parámetro GET _changelist_filters. Es importante que tengas en cuenta esta modificación si tienes plantillas de administración personalizadas o si tus pruebas dependen de las URL anteriores. Si deseas revertir al comportamiento original, puedes establecer la propiedad preserve_filters a False.

La restauración de contraseña de django.contrib.auth utiliza codificación base 64 del PK de User

Las versiones anteriores de Django utilizaban una codificación base 36 del PK principal de User en las vistas y URLs de restauración de contraseña (django.contrib.auth.views.password_reset_confirm()). La codificación base 36 es suficiente si el PK principal del usuario es un entero, sin embargo, con la introducción de modelos de usuarios personalizados en Django 1.5, esta suposición ya no puede ser cierta.

La vista django.contrib.auth.views.password_reset_confirm() ha sido modificada para aceptar el parámetro uidb64 en lugar de uidb36. Si estás restando esta vista, por ejemplo en una plantilla personalizada password_reset_email.html, asegúrate de actualizar tu código.

A continuación, te proporciono las traducciones de los textos originales manteniendo todas sus etiquetas intactas.

Además, si tienes cualquier URL personalizada para el restablecimiento de contraseña, necesitarás actualizarlas reemplazando uidb36 con uidb64 y el guión que sigue ese patrón con una barra. También debes agregar _\- a la lista de caracteres que pueden coincidir con el patrón uidb64.

Por ejemplo:

url(
    r"^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$",
    "django.contrib.auth.views.password_reset_confirm",
    name="password_reset_confirm",
),

become

url(
    r"^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>.+)/$",
    "django.contrib.auth.views.password_reset_confirm",
    name="password_reset_confirm",
),

También podrías querer agregar la capa para apoyar los enlaces antiguos de restablecimiento. Utilizando el ejemplo anterior, modificarías la URL existente reemplazando django.contrib.auth.views.password_reset_confirm con django.contrib.auth.views.password_reset_confirm_uidb36 y también eliminando el argumento name para que no entre en conflicto con la nueva URL:

url(
    r"^reset/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$",
    "django.contrib.auth.views.password_reset_confirm_uidb36",
),

Puedes eliminar este patrón de URL después de que tu aplicación haya sido desplegada con Django 1.6 durante PASSWORD_RESET_TIMEOUT_DAYS.

La serialización por defecto de las sesiones se ha cambiado a JSON

Históricamente, django.contrib.sessions utilizaba pickle para serializar los datos de sesión antes de almacenarlos en el backend. Si estás utilizando el backend de sesión de cookie firmada (signed cookie session backend) y la clave secreta (SECRET_KEY) es conocida por un atacante (no existe una vulnerabilidad inherente en Django que cause su divulgación), el atacante podría insertar una cadena en su sesión que, cuando se desempaqueta, ejecuta código arbitrario en el servidor. La técnica para hacerlo es simple y fácilmente disponible en Internet. Aunque la almacenamiento de cookies firmados firma los datos almacenados en la cookie para prevenir la manipulación, un divulgación inmediata de SECRET_KEY escala a una vulnerabilidad de ejecución de código remoto.

Este ataque se puede mitigar serializando los datos de sesión utilizando JSON en lugar de pickle. Para facilitar esto, Django 1.5.3 introdujo un nuevo parámetro de configuración, SESSION_SERIALIZER, para personalizar el formato de serialización de las sesiones. Por compatibilidad hacia atrás, este parámetro se estableció por defecto en utilizar pickle en Django 1.5.3, pero hemos cambiado el valor por defecto a JSON en 1.6. Si actualizas y cambias de pickle a JSON, las sesiones creadas antes de la actualización se perderán. Aunque la serialización JSON no soporta todos los objetos Python como pickle lo hace, recomendamos altamente utilizar sesiones serializadas en JSON. Ten en cuenta lo siguiente al revisar tu código para determinar si la serialización JSON funcionará para tu aplicación:

  • JSON requiere claves de cadena, por lo que probablemente te encontrarás con problemas si estás utilizando claves no de cadena en request.session.

  • Establecer la expiración de sesión pasando valores de datetime a set_expiry() no funcionará como los valores de datetime no son serializables en JSON. Puedes utilizar valores enteros en su lugar.

See the sesión_serialización documentation for more details.

Cambios en el mapeo objeto-relacional

Django 1.6 contiene muchos cambios en el ORM. Estos cambios se clasifican principalmente en tres categorías:

  1. Correcciones de errores (por ejemplo, cláusulas de unión correctas para relaciones generales, combinación de consultas, promoción y eliminación de uniones)

  2. Preparación de nuevas características. Por ejemplo, el ORM está ahora interno listo para claves foráneas multicolumna.

  3. Limpieza general.

Estos cambios pueden dar lugar a algunos problemas de compatibilidad. Por ejemplo, algunas consultas generarán ahora alias de tabla diferentes. Esto puede afectar a QuerySet.extra(). Además, algunas consultas producirán ahora resultados diferentes. Un ejemplo es exclude(condition) donde la condición es compleja (referenciando multijuntes dentro de Q objects). En muchos casos las consultas afectadas no producían resultados correctos en Django 1.5 pero sí ahora. Desafortunadamente, también hay casos que producen diferentes resultados, pero ni Django 1.5 ni 1.6 producen resultados correctos.

Finalmente, se han realizado muchos cambios en las API internas del ORM.

Miscelánea

  • La clase django.db.models.query.EmptyQuerySet ya no se puede instanciar - solo es usable como una clase de marcador para comprobar si none() ha sido llamado: isinstance(qs.none(), EmptyQuerySet)

  • Si tu código CSS/JavaScript utilizaba a acceder a widgets HTML de entrada por tipo, deberías revisarlo ya que los widgets de entrada con type='text' pueden ahora salir como type='email', type='url' o type='number' dependiendo del tipo correspondiente de campo.

  • Los campos de formulario que contienen un lugar holder en su error_messages deben utilizar ahora siempre un nombre de lugar holder ("Value '%(value)s' is too big" en lugar de "Value '%s' is too big"). Consulte la documentación del campo correspondiente para obtener detalles sobre los nombres de los lugares holders. Los cambios en 1.6 afectan particularmente a DecimalField y ModelMultipleChoiceField.

  • Algunas error_messages para IntegerField, EmailField, IPAddressField, GenericIPAddressField, y SlugField se han suprimido porque duplicaban mensajes de error ya proporcionados por validadores vinculados a los campos.

  • Debido a un cambio en el flujo de validación de formularios, el método coerce de la clase TypedChoiceField debe devolver siempre un valor presente en el atributo choices del campo. Esa limitación se levantará nuevamente en Django 1.7.

  • Han habido cambios en la forma en que se manejan los tiempos de espera en los backends de caché. Pasar explícitamente timeout=None ya no da como resultado el uso del tiempo de espera por defecto. Ahora establecerá un tiempo de espera no expirado. Pasar 0 al backend de memcache ya no utiliza el tiempo de espera por defecto, y ahora establecerá y expirá el valor inmediatamente.

  • La aplicación django.contrib.flatpages utilizaba para fines de depuración a los encabezados HTTP personalizados. Esta funcionalidad no estaba documentada y hacía que la caché fuera ineficaz por lo que ha sido eliminado, junto con su implementación genérica, anteriormente disponible en django.core.xheaders.

  • La XViewMiddleware ha sido movida de django.middleware.doc a django.contrib.admindocs.middleware porque es un detalle de implementación de admindocs, que no resultó ser reutilizable en general.

  • GenericIPAddressField ahora solo permitirá valores blank si también se permiten los valores null. Crear un campo GenericIPAddressField donde se permite blank pero no null provocará un error de validación del modelo porque los valores blank siempre se almacenan como null. Anteriormente, almacenar un valor blank en un campo que no permitía null causaba una excepción de base de datos en tiempo de ejecución.

  • Si se levanta una excepción NoReverseMatch desde un método cuando se está renderizando un plantilla, no se silencia. Por ejemplo, {{ obj.view_href }} causará que la rendición de plantillas fallen si view_href() levanta NoReverseMatch. No hay cambios en el {% url %} tag, causa la rendición de plantillas fallar como siempre cuando se levanta NoReverseMatch.

  • django.test.Client.logout() ahora llama a django.contrib.auth.logout(), que enviará el señal user_logged_out().

  • Las vistas de autenticación Authentication views ahora se invocan por nombre, no por su ubicación en django.contrib.auth.views. Si estás utilizando las vistas sin un name, debes actualizar tus urlpatterns para utilizar django.conf.urls.url() con el parámetro name. Por ejemplo:

    (r"^reset/done/$", "django.contrib.auth.views.password_reset_complete")
    

    become

    url(
        r"^reset/done/$",
        "django.contrib.auth.views.password_reset_complete",
        name="password_reset_complete",
    )
    
  • RedirectView ahora tiene un atributo pattern_name que le permite elegir el objetivo mediante la reversión de la URL.

  • En Django 1.4 y 1.5, una cadena vacía se consideraba involuntariamente no válida como contraseña. Esto significaba que set_password() guardaría una contraseña en blanco como una contraseña inutilizable como lo hace set_unusable_password(), y así check_password() siempre devolvía False para contraseñas en blanco. Esto se ha corregido en esta versión: las contraseñas en blanco ahora son válidas.

  • La vista de administración changelist_view aceptaba previamente un parámetro GET pop para significar que debía ser mostrada en una ventana emergente. Este parámetro ha sido renombrado a _popup para estar consistente con el resto de las vistas de administración. Debes actualizar tus plantillas personalizadas si utilizan el nombre anterior del parámetro.

  • validate_email() ahora acepta direcciones de correo electrónico con localhost como dominio.

  • La nueva opción makemessages --keep-pot previene la eliminación del archivo temporal .pot generado antes de crear el archivo .po.

  • El excepción no documentada django.core.servers.basehttp.WSGIServerException ha sido eliminada. Utiliza socket.error proporcionado por la biblioteca estándar en su lugar. Este cambio también se lanzó en Django 1.5.5.

  • La firma de django.views.generic.base.RedirectView.get_redirect_url() ha cambiado y ahora acepta argumentos posicionales (*args, **kwargs). Cualquier grupo capturado sin nombre ahora se pasará a get_redirect_url() lo que puede dar lugar a un TypeError si no actualizas la firma de tu método personalizado.

Características obsoletas en 1.6

APIs de gestión de transacciones

La gestión de transacciones se ha revisado completamente en Django 1.6, y las actuales APIs están obsoletas:

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

  • django.db.transaction.autocommit

  • django.db.transaction.commit_on_success

  • django.db.transaction.commit_manually

  • la configuración TRANSACTIONS_MANAGED

django.contrib.comments

El marco de comentarios de Django ha sido descontinuado y ya no está soportado. Estará disponible en Django 1.6 y 1.7, y se eliminará en Django 1.8. La mayoría de los usuarios estarán mejor servidos con una solución personalizada o un producto hospedado como Disqus.

El código anteriormente conocido como django.contrib.comments está todavía disponible en un repositorio externo.

Soporte para versiones de PostgreSQL anteriores a 8.4

La fecha límite del período de soporte upstream se alcanzó en diciembre de 2011 para PostgreSQL 8.2 y en febrero de 2013 para 8.3. Como consecuencia, Django 1.6 establece 8.4 como la versión mínima de PostgreSQL que oficialmente admite.

You’re strongly encouraged to use the most recent version of PostgreSQL available, because of performance improvements and to take advantage of the native streaming replication available in PostgreSQL 9.x.

Cambios en cycle y firstof

El sistema de plantillas generalmente escapa todas las variables para evitar ataques XSS. Sin embargo, debido a un accidente histórico, los etiquetas cycle y firstof renderizan sus argumentos tal como están.

Django 1.6 inicia un proceso para corregir esta inconsistencia. La biblioteca de plantillas future proporciona implementaciones alternativas de cycle y firstof que autoescapan sus entradas. Si estás utilizando estas etiquetas, te recomendamos incluir la siguiente línea en la parte superior de tus plantillas para habilitar el nuevo comportamiento:

{% load cycle from future %}

o:

{% load firstof from future %}

Las etiquetas que implementan el antiguo comportamiento han sido deprecadas y, en Django 1.8, el antiguo comportamiento será reemplazado con el nuevo comportamiento. Para asegurar la compatibilidad con versiones futuras de Django, las plantillas existentes deben ser modificadas para utilizar las versiones future.

Si es necesario, puedes deshabilitar temporalmente la auto-escapada con mark_safe() o {% autoescape off %}.

Configuración CACHE_MIDDLEWARE_ANONYMOUS_ONLY

CacheMiddleware y UpdateCacheMiddleware solían proporcionar una forma de cachear solicitudes solo si no habían sido realizadas por un usuario conectado. Este mecanismo era en gran medida ineficaz porque el middleware toma correctamente en cuenta la cabecera HTTP Vary: Cookie, y esta cabecera se está estableciendo en diversas ocasiones, como:

  • al acceder a la sesión,

  • using CSRF protection, que está activado por defecto, o

  • utilizando una biblioteca cliente que establece cookies, como Google Analytics.

Esto hace que la caché funcione efectivamente en una base de sesión independientemente del valor de CACHE_MIDDLEWARE_ANONYMOUS_ONLY.

método _has_changed en widgets

Si definiste tus propios widgets de formulario y definiste el método _has_changed en un widget, debes definir ahora este método en el campo de formulario en sí mismo.

atributo _meta del modelo module_name

Model._meta.module_name fue renombrado a model_name. A pesar de ser una API privada, seguirá un camino de deprecación regular.

get_(add|change|delete)_permission métodos del _meta del modelo

Los métodos Model._meta.get_(add|change|delete)_permission fueron deprecados. Incluso si no formaban parte de la API pública, también seguirán un camino de deprecación regular. Puedes reemplazarlos con django.contrib.auth.get_permission_codename('acción', Model._meta) donde 'acción' es 'add', 'change' o 'delete'.

Los métodos get_query_set y similares fueron renombrados a get_queryset

Los métodos que devuelven un QuerySet como Manager.get_query_set o ModelAdmin.queryset han sido renombrados a get_queryset.

Si estás escribiendo una biblioteca que implementa, por ejemplo, el método Manager.get_query_set, y necesitas soportar versiones antiguas de Django, deberías renombrar el método y agregar condicionalmente un alias con el nombre antiguo:

class CustomManager(models.Manager):
    def get_queryset(self):
        pass  # ...

    if django.VERSION < (1, 6):
        get_query_set = get_queryset

    # For Django >= 1.6, models.Manager provides a get_query_set fallback
    # that emits a warning when used.

Si estás escribiendo una biblioteca que necesita llamar al método get_queryset y debe soportar versiones antiguas de Django, deberías escribir:

get_queryset = (
    some_manager.get_query_set
    if hasattr(some_manager, "get_query_set")
    else some_manager.get_queryset
)
return get_queryset()  # etc

En el caso general de un administrador personalizado que implementa su propio método get_queryset y llama a ese método, y necesita funcionar con versiones antiguas de Django, y bibliotecas que aún no han sido actualizadas, es útil definir un método get_queryset_compat como se muestra a continuación y utilizarlo internamente en tu administrador:

class YourCustomManager(models.Manager):
    def get_queryset(self):
        return YourCustomQuerySet()  # for example

    if django.VERSION < (1, 6):
        get_query_set = get_queryset

    def active(self):  # for example
        return self.get_queryset_compat().filter(active=True)

    def get_queryset_compat(self):
        get_queryset = (
            self.get_query_set if hasattr(self, "get_query_set") else self.get_queryset
        )
        return get_queryset()

Esto ayuda a minimizar los cambios necesarios, pero también funciona correctamente en el caso de subclases (como RelatedManagers desde Django 1.5) que pueden sobreescribir tanto get_query_set como get_queryset.

La vista y la configuración URL shortcut

La vista shortcut fue movida desde django.views.defaults a django.contrib.contenttypes.views poco después de la versión 1.0, pero nunca se depreció el antiguo emplazamiento. Este olvido se corrigió en Django 1.6 y debes utilizar ahora la nueva ubicación.

La configuración de URLs django.conf.urls.shortcut también estaba desaconsejada. Si la estás incluyendo en una configuración de URLs, simplemente reemplaza:

(r"^prefix/", include("django.conf.urls.shortcut")),

con:

(
    r"^prefix/(?P<content_type_id>\d+)/(?P<object_id>.*)/$",
    "django.contrib.contenttypes.views.shortcut",
),

ModelForm sin fields o exclude

Anteriormente, si deseabas que una ModelForm utilizara todos los campos del modelo, simplemente podías omitir la atributo Meta.fields, y se utilizarían todos los campos.

Puede dar lugar a problemas de seguridad donde los campos se agregan al modelo y, de manera involuntaria, se vuelven editables automáticamente por parte de los usuarios finales. En algunos casos, particularmente con campos booleanos, es posible que este problema sea completamente invisible. Esto es una forma de vulnerabilidad de asignación en masa.

Por esta razón, este comportamiento está desaconsejado y se considera obsoleto, y utilizar la opción Meta.exclude se desaconseja fuertemente. En su lugar, todos los campos que se pretenden incluir en el formulario deben enumerarse explícitamente en la atributo fields.

Si esta preocupación de seguridad no se aplica en tu caso, hay una forma abreviada para indicar explícitamente que todos los campos deben usarse: utilice el valor especial "__all__" para la atributo de campos:

class MyModelForm(ModelForm):
    class Meta:
        fields = "__all__"
        model = MyModel

Si tienes formularios de modelo personalizados que solo necesitan ser utilizados en la administración, hay otra opción. La administración tiene sus propias métodos para definir campos (fieldsets, etc.), por lo que agregar una lista de campos al formulario de modelo es redundante. En su lugar, simplemente omite la clase interna Meta del formulario de modelo o el atributo model de Meta. Dado que la subclase de ModelAdmin sabe qué modelo se trata, puede agregar los atributos necesarios para derivar un formulario de modelo funcional. Este comportamiento también funciona en versiones anteriores de Django.

UpdateView y CreateView sin campos explícitos

Los textos traducidos son:

Por esta razón, si utilizas estas vistas para editar modelos, debes suministrar también el atributo fields (nuevo en Django 1.6), que es una lista de campos del modelo y funciona de la misma manera que el atributo Meta.fields de ModelForm. Alternativamente, puedes establecer el atributo form_class a un ModelForm que defina explícitamente los campos a utilizar. Definir una subclase de UpdateView o CreateView para ser utilizada con un modelo pero sin una lista explícita de campos es deprecated.

Manipulación del texto de ayuda de los campos de formulario de modelos para campos ManyToManyField

Todas las manipulaciones especiales del atributo help_text de los campos de modelos ManyToManyField realizadas por los campos de modelo estándar o formularios de modelo, como se describe en Texto de ayuda de campos de formulario de modelo para campos ManyToManyField anteriormente, están deprecated y serán eliminadas en Django 1.8.

El texto de ayuda de estos campos deberá ser gestionado ya sea por aplicaciones, campos de formulario personalizados o widgets, al igual que sucede con el resto de tipos de campos de modelo.