Notas de lanzamiento de Django 1.9

Diciembre 1, 2015

Bienvenido a Django 1.9!

Estas notas de lanzamiento cubren las nuevas características, así como algunos cambios que no son compatibles con versiones anteriores <backwards-incompatible-1.9>` que debes tener en cuenta al actualizar desde Django 1.8 o versiones más antiguas. Hemos eliminado algunas características que han llegado a su fin de ciclo de deprecación, y hemos comenzado el proceso de deprecación para algunas características <deprecated-features-1.9>`.

Consulte la guía Cómo actualizar Django a una versión más reciente si estás actualizando un proyecto existente.

Compatibilidad con Python

Django 1.9 requiere Python 2.7, 3.4 o 3.5. Recomendamos y solo oficialmente apoyamos la última versión de cada serie.

La serie Django 1.8 es la última que admite Python 3.2 y 3.3.

¿Qué hay de nuevo en Django 1.9

Ejecutar acciones después de un commit de transacción

El nuevo on_commit() hook permite ejecutar acciones después de que una transacción de base de datos se haya comprometido con éxito. Esto es útil para tareas como enviar correos electrónicos de notificación, crear tareas programadas o invalidar cachés.

Esta funcionalidad del paquete django-transaction-hooks ha sido integrada en Django.

Validación de contraseñas

Django ahora ofrece validación de contraseñas para ayudar a prevenir el uso de contraseñas débiles por los usuarios. La validación está integrada en las formas de cambio y restablecimiento de contraseña incluidas y es sencilla de integrar en cualquier otro código. La validación se realiza mediante uno o más validadores, configurados en la nueva AUTH_PASSWORD_VALIDATORS configuración.

Four validadores están incluidos en Django, que pueden hacer cumplir una longitud mínima, comparar la contraseña con las características del usuario como su nombre, asegurarse de que las contraseñas no sean numéricas enteramente o comprobar contra una lista de contraseñas comunes incluida. Puedes combinar múltiples validadores y algunos validadores tienen opciones de configuración personalizadas. Por ejemplo, puedes elegir proporcionar una lista de contraseñas comunes personalizada. Cada validador proporciona un texto de ayuda para explicar sus requisitos al usuario.

Por defecto, no se realiza ninguna validación y todas las contraseñas son aceptadas, por lo que si no estableces AUTH_PASSWORD_VALIDATORS, no verás ningún cambio. En proyectos nuevos creados con el plantilla de inicio predeterminado startproject, un conjunto simple de validadores está habilitado. Para habilitar la validación básica en las formas de autenticación incluidas para tu proyecto, podrías establecer, por ejemplo:

AUTH_PASSWORD_VALIDATORS = [
    {
        "NAME": "django.contrib.auth.password_validation.UserAttributeSimilarityValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.MinimumLengthValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.CommonPasswordValidator",
    },
    {
        "NAME": "django.contrib.auth.password_validation.NumericPasswordValidator",
    },
]

Consulte Validación de contraseñas para obtener más detalles.

Mixins de permisos para vistas basadas en clases

Django ahora viene con los mixins AccessMixin, LoginRequiredMixin, PermissionRequiredMixin y UserPassesTestMixin para proporcionar la funcionalidad de los decoradores django.contrib.auth.decorators para vistas basadas en clases. Estos mixins han sido tomados de, o al menos inspirados por, el proyecto django-braces.

Hay algunas diferencias entre la implementación de Django y django-braces, aunque:

  • La raise_exception atributo solo puede ser True o False. Las excepciones personalizadas o llamables no están soportadas.

  • El método handle_no_permission() no toma un argumento request. La solicitud actual está disponible en self.request.

  • La función de prueba personalizada test_func() de UserPassesTestMixin no toma un argumento user. El usuario actual está disponible en self.request.user.

  • El atributo permission_required admite una cadena (definiendo una permiso) o una lista/tupla de cadenas (definiendo múltiples permisos) que deben cumplirse para otorgar acceso.

  • El nuevo atributo permission_denied_message permite pasar un mensaje a la excepción PermissionDenied.

Nueva estilización para contrib.admin

La interfaz de administración tiene un diseño moderno y plano con nuevos iconos SVG que se ven perfectos en pantallas HiDPI. Aún así, proporciona una experiencia funcional completa a los navegadores YUI’s A-grade . Los navegadores más antiguos pueden experimentar niveles variables de degradación suave.

Ejecutar pruebas en paralelo

El comando test ahora admite la opción --parallel para ejecutar las pruebas de un proyecto en múltiples procesos en paralelo.

Cada proceso tiene su propia base de datos. Debes asegurarte de que los casos de prueba diferentes no accedan a los mismos recursos. Por ejemplo, los casos de prueba que interactúen con el sistema de archivos deben crear un directorio temporal para su uso propio.

Esta opción está habilitada por defecto para la suite de pruebas de Django proporcionada:

  • el SO lo soporta (todos menos Windows)

  • el backend de base de datos lo soporta (todos los backends integrados excepto Oracle)

Características menores

django.contrib.admin

  • Las vistas de administración ahora tienen atributos model_admin o admin_site.

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

  • ModelAdmin.get_list_select_related() se agregó para permitir cambiar los valores de select_related() utilizados en la consulta de la lista de cambios del administrador según la solicitud.

  • La variable de contexto available_apps, que enumera las aplicaciones disponibles para el usuario actual, ha sido agregada a la AdminSite.each_context() método.

  • AdminSite.empty_value_display y ModelAdmin.empty_value_display se agregaron para sobreescribir la visualización de valores vacíos en la lista de cambios del administrador. También puedes personalizar el valor para cada campo.

  • Se agregaron eventos jQuery cuando una forma inline es añadida o eliminada en la página de formulario de cambio.

  • El widget de selector de hora incluye la opción “6 p.m” para consistencia al tener opciones predefinidas cada 6 horas.

  • La generación de slugs de JavaScript ahora admite caracteres rumano.

django.contrib.admindocs

  • La sección del modelo de admindocs ahora también describe métodos que toman argumentos, en lugar de ignorarlos.

django.contrib.auth

  • El recuento de iteraciones por defecto para el algoritmo de hash de contraseña PBKDF2 ha sido aumentado en un 20%. Este cambio compatible hacia atrás no afectará a los usuarios que hayan sobrescrito django.contrib.auth.hashers.PBKDF2PasswordHasher para cambiar el valor por defecto.

  • El BCryptSHA256PasswordHasher ahora actualizará las contraseñas si su atributo rounds es cambiado.

  • AbstractBaseUser y BaseUserManager fueron movidos a un nuevo módulo django.contrib.auth.base_user para que puedan ser importados sin incluir django.contrib.auth en INSTALLED_APPS (lo que provocaba una advertencia de desuso en versiones anteriores y ya no está soportado en Django 1.9).

  • El argumento de permiso de la función permission_required() acepta todos los tipos de iterables, no solo listas y tuplas.

  • La nueva clase PersistentRemoteUserMiddleware permite utilizar REMOTE_USER para configuraciones en las que el encabezado se pobló únicamente en páginas de inicio de sesión en lugar de cada solicitud en la sesión.

  • La vista django.contrib.auth.views.password_reset() acepta un parámetro extra_email_context.

django.contrib.contenttypes

django.contrib.gis

  • Todos los métodos de GeoQuerySet han sido descontinuados y reemplazados por funciones equivalentes del motor de base de datos </ref/contrib/gis/functions>. Tan pronto como los métodos legados hayan sido reemplazados en su código, incluso deberían poder eliminar el especial GeoManager de sus clases GIS habilitadas.

  • La interfaz GDAL ahora admite instanciar objetos GDALRaster basados en archivos y memoria desde datos brutos. Se han agregado setters para propiedades del raster como la proyección o los valores de píxeles.

  • Para usuarios de PostGIS, el nuevo campo RasterField permite almacenar objetos GDALRaster. Soporta la creación automática del índice espacial y la reproyección al guardar un modelo. No soporta aún consultas espaciales.

  • La nueva método GDALRaster.warp() permite warpear un raster especificando propiedades del raster objetivo como origen, ancho, alto o tamaño de píxeles (entre otros).

  • El nuevo método GDALRaster.transform() permite transformar un raster en un sistema de referencia espacial diferente especificando una srid objetivo.

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

  • Se ha actualizado la versión por defecto del paquete OpenLayers incluido en los widgets desde 2.13 a 2.13.1.

django.contrib.postgres

django.contrib.sesiones

django.contrib.sitios

  • get_current_site() ahora maneja el caso en que request.get_host() devuelve domain:port, por ejemplo, example.com:80. Si la búsqueda falla porque el host no coincide con un registro en la base de datos y el host tiene un puerto, se elimina el puerto y se vuelve a intentar la búsqueda con solo la parte del dominio.

django.contrib.syndication

  • Se ha agregado soporte para múltiples enclosures por item de feed. Si se definen múltiples enclosures en una fuente RSS, se levanta una excepción ya que las fuentes RSS, a diferencia de las fuentes Atom, no admiten múltiples enclosures por item de feed.

Cache

  • django.core.cache.backends.base.BaseCache ahora tiene un método get_or_set().

  • django.views.decorators.cache.never_cache() ahora envía encabezados más persuasivos (se agregaron no-cache, no-store, must-revalidate a Cache-Control) para prevenir mejor la caché. Esto también se agregó en Django 1.8.8.

CSRF

  • El nombre del encabezado de solicitud utilizado para la autenticación CSRF se puede personalizar con CSRF_HEADER_NAME.

  • El encabezado referente CSRF ahora se valida contra el parámetro de configuración CSRF_COOKIE_DOMAIN si está establecido. Consulte Cómo funciona para obtener más detalles.

  • La nueva configuración CSRF_TRUSTED_ORIGINS proporciona una forma de permitir solicitudes cruzadas de origen inseguras (por ejemplo, POST) sobre HTTPS.

Base de datos

  • El backend PostgreSQL (django.db.backends.postgresql_psycopg2) también está disponible como django.db.backends.postgresql. El nombre antiguo seguirá estando disponible para compatibilidad hacia atrás.

Almacenamiento de archivos

Formularios

  • ModelForm acepta la nueva opción Meta field_classes para personalizar el tipo de los campos. Consulte Sobreescribir los campos por defecto para obtener más detalles.

  • Puedes especificar ahora el orden en que se renderizan los campos del formulario con el atributo field_order, el argumento constructor field_order o el método order_fields().

  • Se puede especificar un prefijo de formulario dentro de una clase de formulario, no solo cuando se instancia un formulario. Consulte Prefijos para formularios para obtener más detalles.

  • Ahora puedes especificar argumentos de palabra clave <custom-formset-form-kwargs> que deseas pasar a la construcción de formularios en un conjunto de formularios.

  • SlugField acepta ahora un argumento allow_unicode para permitir caracteres Unicode en slugs.

  • CharField acepta ahora un argumento strip para eliminar los espacios en blanco de inicio y fin del dato de entrada. Dado que esto es distinto al comportamiento anterior, es diferente a las versiones anteriores.

  • Los campos de formulario admiten ahora el argumento disabled, lo que permite que el widget del campo se muestre deshabilitado por los navegadores.

  • Es posible personalizar los campos vinculados reemplazando el método get_bound_field() de un campo.

Vistas Genericas

  • Las vistas basadas en clases generadas mediante as_view() tienen ahora atributos view_class y view_initkwargs.

  • La función method_decorator() puede usarse con una lista o tupla de decoradores. También se puede usar para decorar clases en lugar de métodos <decorating-class-based-views>.

Internacionalización

  • La vista django.views.i18n.set_language() ahora redirige correctamente a URLs traducidas <url-internationalization>, cuando están disponibles.

  • La función django.views.i18n.javascript_catalog() ahora funciona correctamente si se utiliza varias veces con diferentes configuraciones en la misma página.

  • La función django.utils.timezone.make_aware() obtuvo un argumento is_dst para ayudar a resolver tiempos ambiguos durante las transiciones de horario de verano.

  • Puedes utilizar ahora variantes de localización soportadas por gettext. Estas se utilizan generalmente para idiomas que pueden escribirse en diferentes scripts, por ejemplo, latín y cirílico (por ejemplo, be@latin).

  • Se ha agregado la vista django.views.i18n.json_catalog() para ayudar a construir una biblioteca de i18n personalizada en el lado del cliente sobre las traducciones de Django. Devuelve un objeto JSON que contiene un catálogo de traducciones, configuraciones de formato y una regla de pluralidad.

  • Se ha agregado la atributo name_translated al objeto devuelto por el etiqueta de plantilla get_language_info. También se ha agregado una correspondiente filtro de plantilla: language_name_translated.

  • Puedes ejecutar ahora compilemessages desde la carpeta raíz de tu proyecto y encontrará todos los archivos de mensajes de aplicación que fueron creados por makemessages.

  • makemessages llama ahora a xgettext una vez por directorio de localización en lugar de una vez por archivo translatable. Esto acelera las construcciones de localización.

  • La etiqueta blocktrans admite asignar su salida a una variable utilizando asvar.

  • Están disponibles dos nuevos idiomas: español de Colombia y gaélico escocés.

Comandos de Gestión

  • El nuevo comando sendtestemail te permite enviar un correo electrónico de prueba para confirmar fácilmente que el envío de correos electrónicos a través de Django está funcionando.

  • Para aumentar la legibilidad del código SQL generado por sqlmigrate, el código SQL generado para cada operación de migración se precede con la descripción de la operación.

  • La salida del comando dumpdata ahora está ordenada determinísticamente. Además, cuando se especifica la opción --output, también muestra un indicador de progreso en la terminal.

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

  • El comando startapp crea un archivo apps.py. Dado que no utiliza default_app_config (una API desaconsejada), debes especificar la ruta del config de la app, por ejemplo 'polls.apps.PollsConfig', en INSTALLED_APPS para que se utilice (en lugar de solo 'polls').

  • Al utilizar el backend PostgreSQL, el comando dbshell puede conectarse a la base de datos utilizando la contraseña del archivo de configuración (en lugar de requerirla que se ingrese manualmente).

  • El paquete django puede ejecutarse como un script, es decir python -m django, lo que comportará igual que django-admin.

  • Los comandos de gestión que tienen la opción --noinput ahora también aceptan --no-input como alias para esa opción.

Migraciones

  • Las migraciones iniciales ahora están marcadas con un atributo de clase initial = True lo que permite a migrate --fake-initial detectar fácilmente las migraciones iniciales.

  • Se ha agregado soporte para la serialización de instancias functools.partial y LazyObject.

  • Al proporcionar None como valor en MIGRATION_MODULES, Django considerará la app sin migraciones.

  • Al aplicar las migraciones, el paso «Renderizado de estados de modelos» que se muestra al ejecutar migrate con verbosidad 2 o superior ahora solo calcula los estados para las migraciones que ya han sido aplicadas. Los estados de modelos para las migraciones que se están aplicando se generan en demanda, lo que reduce drásticamente la cantidad de memoria requerida.

    Sin embargo, esta mejora no está disponible al desaplicar migraciones y por tanto sigue requiriendo la precomputación y almacenamiento de los estados de migración intermedios.

    Esta es la traducción de los textos:

  • El comando squashmigrations ahora admite especificar la migración inicial desde la cual las migraciones se compactarán.

Modelos

  • QuerySet.bulk_create() ahora funciona en modelos de proxy.

  • La configuración de base de datos obtuvo una opción TIME_ZONE para interactuar con bases de datos que almacenan fechas y horas en tiempo local y no admiten zonas horarias cuando USE_TZ es True.

  • Se agregó el método RelatedManager.set() a los administradores relacionados creados por ForeignKey, GenericForeignKey y ManyToManyField.

  • El método add() en una clave foránea inversa ahora tiene un parámetro bulk para permitir ejecutar una sola consulta independientemente del número de objetos que se están agregando, en lugar de una consulta por objeto.

  • Se agregó el parámetro keep_parents a Model.delete() para permitir borrar solo los datos de un hijo en un modelo que utiliza herencia multi-tabla.

  • Model.delete() y QuerySet.delete() devuelven el número de objetos borrados.

  • Se agregó un sistema de comprobación para prevenir definir tanto Meta.ordering como order_with_respect_to en el mismo modelo.

  • Las consultas Fecha y hora se pueden encadenar con otras consultas (como exact, gt, lt, etc.). Por ejemplo: Entry.objects.filter(pub_date__month__gt=6).

  • Los lookups de tiempo (hora, minuto, segundo) ahora están soportados por TimeField para todos los backends de base de datos. El soporte para backends distintos a SQLite se agregó pero no fue documentado en Django 1.7.

  • Puedes especificar el parámetro output_field de la función agregada Avg para agrupar sobre columnas no numéricas, como DurationField.

  • Se agregó el lookup date a DateTimeField para permitir consultar el campo solo por la parte de fecha.

  • Se agregaron las funciones de base de datos Greatest y Least.

  • Se agregó la función de base de datos Now, que devuelve la fecha y hora actual.

  • Transform ahora es una subclase de Func() lo que permite utilizar Transforms en el lado derecho de una expresión, al igual que las Func regulares. Esto permite registrar algunas funciones de base de datos como Length, Lower y Upper como transformaciones.

  • SlugField ahora acepta un argumento allow_unicode para permitir caracteres Unicode en los slugs.

  • Se agregó soporte para referenciar anotaciones en QuerySet.distinct().

  • connection.queries muestra consultas con parámetros sustituidos en SQLite.

  • Las expresiones de consulta Query expressions ahora se pueden utilizar al crear nuevas instancias de modelos utilizando save(), create() y bulk_create().

Solicitudes y respuestas

  • A menos que se establezca explícitamente el valor de HttpResponse.reason_phrase, ahora está determinado por el valor actual de HttpResponse.status_code. Modificar el valor de status_code fuera del constructor también modificará el valor de reason_phrase.

  • La vista de depuración muestra ahora detalles de excepciones encadenadas en Python 3.

  • Las vistas de errores por defecto 40x ahora aceptan un segundo parámetro posicional, la excepción que desencadenó la vista.

  • Los manejadores de errores de vistas ahora admiten TemplateResponse, comúnmente utilizado con vistas basadas en clases.

  • Las excepciones levantadas por el método render() se pasan ahora al método process_exception() de cada middleware.

  • Los middleware de solicitud pueden establecer ahora HttpRequest.urlconf en None para revertir cualquier cambio realizado por middleware previos y regresar a utilizar la ROOT_URLCONF.

  • La comprobación de DISALLOWED_USER_AGENTS en CommonMiddleware ahora levanta una excepción PermissionDenied en lugar de devolver un HttpResponseForbidden para que se invoque a handler403.

  • Se agregó la función HttpRequest.get_port() para obtener el puerto de origen de la solicitud.

  • Se agregó el parámetro json_dumps_params a JsonResponse para permitir pasar argumentos clave al llamado json.dumps() utilizado para generar la respuesta.

  • La clase BrokenLinkEmailsMiddleware ahora ignora los 404 cuando el referente es igual a la URL solicitada. Para evitar la comprobación del referente vacío ya implementada, algunos bots web establecen el referente en la URL solicitada.

Plantillas

  • Los textos traducidos son:

  • Se agregó un método Context.setdefault().

  • El logger django.template se agregó y incluye los siguientes mensajes:

    • Un mensaje de nivel DEBUG para variables de contexto faltantes.

    • Un mensaje de nivel WARNING para excepciones no atrapadas que se levantan durante la renderización de un {% include %} cuando el modo depuración está desactivado (útil ya que {% include %} silencia la excepción y devuelve una cadena vacía).

  • El etiqueta de plantilla firstof admite almacenar la salida en una variable utilizando “as”.

  • Se puede utilizar el método Context.update() como administrador de contexto.

  • Los cargadores de plantillas de Django pueden extender las plantillas de manera recursiva.

  • La página de depuración post mortem ahora incluye la salida de cada motor que está instalado.

  • Se agregó la integración de la página de depuración para motores de plantilla personalizados: Debug page integration.

  • El texto traducido es el siguiente:

  • Los filtros timesince y timeuntil fueron mejorados para tratar años bisiestos cuando se les da grandes rangos temporales.

  • El etiqueta include ahora almacena objetos de plantillas parseadas durante la renderización de plantillas, lo que acelera el uso en lugares como los bucles for.

Pruebas

  • Se agregó el método json() del cliente de prueba para dar acceso al cuerpo de respuesta como JSON.

  • Se agregó el método force_login() del cliente de prueba. Utilice este método para simular el efecto de un usuario que inicia sesión en el sitio, saltando los pasos de autenticación y verificación de login().

URLs

  • Las afirmaciones de mirada a la red de expresiones regulares ahora están permitidas en patrones de URL.

  • El espacio de nombres de aplicación puede configurarse utilizando un atributo app_name en el módulo o objeto incluido. También se puede configurar pasando una tupla de 2 elementos (<lista de patrones>, <espacio de nombres de aplicación>) como primer argumento a include().

  • Se han agregado comprobaciones del sistema para errores comunes en los patrones de URL.

Validadores

  • Se agregó la función django.core.validators.int_list_validator() para generar validadores de cadenas que contengan números separados por un carácter personalizado.

  • La clase EmailValidator <~django.core.validators.EmailValidator> ahora limita el largo de los nombres de dominio a 63 caracteres por RFC 1034.

  • Se han agregado las siguientes traducciones:

Cambios incompatibles con lo anterior en 1.9

Advertencia

Además de los cambios descritos en esta sección, asegúrese de revisar la Características eliminadas en 1.9 para las características que han alcanzado el final de su ciclo de deshabilitación y por lo tanto han sido eliminadas. Si no ha actualizado su código dentro del plazo de deshabilitación para una característica determinada, su eliminación puede aparecer como un cambio incompatibles con lo anterior.

Backend de base de datos API

  • Un par de nuevos tests dependen de la capacidad del backend para introspeccionar los valores por defecto de las columnas (devolviendo el resultado como Field.default). Puede establecer la característica de base de datos can_introspect_default en False si su backend no implementa esto. Es posible que desee revisar la implementación en los backends que incluye Django para referencia (#24245).

  • Se desaconseja registrar un adaptador o convertidor global a nivel del módulo DB-API para manejar información de zona horaria de valores datetime pasados como parámetros de consulta o devueltos como resultados de consultas en bases de datos que no admiten zonas horarias. Puede conflictuar con otras bibliotecas.

    La forma recomendada de agregar una zona horaria a valores datetime recuperados desde la base de datos es registrar un convertidor para DateTimeField en DatabaseOperations.get_db_converters().

    Se eliminó la característica de base de datos needs_datetime_string_cast. Los backends de bases de datos que la establecen deben registrar un convertidor en su lugar, tal como se explica anteriormente.

  • Los métodos DatabaseOperations.value_to_db_<type>() fueron renombrados a adapt_<type>field_value() para reflejar los métodos convert_<type>field_value().

  • Para utilizar la nueva búsqueda de fechas, los backends de bases de datos tercerizados pueden necesitar implementar el método DatabaseOperations.datetime_cast_date_sql().

  • Se agregó el método DatabaseOperations.time_extract_sql(). Llama al método existente date_extract_sql(). Este método se sobrescribe por el backend SQLite para agregar búsquedas de tiempo (hora, minuto, segundo) a TimeField, y puede ser necesario por los backends de bases de datos tercerizados.

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

  • Para apoyar la paralelización de pruebas, debes implementar el método DatabaseCreation._clone_test_db() y establecer DatabaseFeatures.can_clone_databases = True. Puede tener que ajustar DatabaseCreation.get_test_db_clone_settings().

Las configuraciones predeterminadas que eran tuplas ahora son listas

Las configuraciones predeterminadas en django.conf.global_settings eran una combinación de listas y tuplas. Todas las configuraciones que eran anteriormente tuplas ahora son listas.

La atributo is_usable en cargadores de plantillas ha sido eliminado

Los cargadores de plantillas de Django requerían previamente un atributo is_usable definido. Si se configuraba un cargador en las opciones de plantilla y este atributo era False, el cargador sería ignorado silenciosamente. En la práctica, esto solo se utilizó por el cargador de huevo para detectar si estaba instalada setuptools. El atributo is_usable ahora ha sido eliminado y el cargador de huevo falla en tiempo de ejecución si no está instalada setuptools.

Cargar cargadores de plantillas basados en filesystem capturan excepciones más específicas

Al utilizar los cargadores de plantillas filesystem.Loader o app_directories.Loader, las versiones anteriores de Django levantaban una error TemplateDoesNotExist si la fuente de la plantilla existía pero era inaccesible. Esto podía suceder en muchas circunstancias, como si Django no tuviera permisos para abrir el archivo o si la fuente de la plantilla fuera un directorio. Ahora, Django silencia solo la excepción si la fuente de la plantilla no existe. Todas las otras situaciones hacen que se levante el error original IOError.

Redirecciones HTTP ya no forzadas a URIs absolutas

Las redirecciones relativas ya no se convierten en URIs absolutas. RFC 2616 requería que la cabecera Location en las respuestas de redirección fuera una URI absoluta, pero ha sido superada por RFC 7231, que permite URIs relativas en Location, reconociendo la práctica real de los agentes de usuario, casi todos los cuales los soportan.

Consecuentemente, las URLs esperadas pasadas a assertRedirects ya no deben incluir generalmente el esquema y la parte del dominio de las URL. Por ejemplo, self.assertRedirects(response, 'http://testserver/some-url/') debe ser reemplazado por self.assertRedirects(response, '/some-url/') (a menos que la redirección contuviera específicamente una URL absoluta).

En el caso raro de que necesites el comportamiento antiguo (descubierto con una versión antigua de Apache con mod_scgi que interpreta una redirección relativa como una «redirección interna»), puedes restaurarlo escribiendo un middleware personalizado:

class LocationHeaderFix(object):
    def process_response(self, request, response):
        if "Location" in response:
            response["Location"] = request.build_absolute_uri(response["Location"])
        return response

Se ha dejado de apoyar PostgreSQL 9.0

El soporte upstream para PostgreSQL 9.0 terminó en septiembre de 2015. Como consecuencia, Django 1.9 establece 9.1 como la versión mínima de PostgreSQL que oficialmente admite.

Se ha dejado de apoyar Oracle 11.1

El soporte upstream para Oracle 11.1 terminó en agosto de 2015. Como consecuencia, Django 1.9 establece 11.2 como la versión mínima de Oracle que oficialmente admite.

Se eliminan las plantillas LoaderOrigin y StringOrigin

En versiones anteriores de Django, cuando se inicializaba un motor de plantillas con debug como True, se establecía una instancia de django.template.loader.LoaderOrigin o django.template.base.StringOrigin como el atributo origin en la objeto de plantilla. Estas clases han sido combinadas en Origin y ahora siempre se establece, independientemente del ajuste de depuración del motor. Para un nivel mínimo de compatibilidad hacia atrás, los nombres de clase antiguos se mantendrán como alias a la nueva clase Origin hasta Django 2.0.

Cambios en la configuración de registro por defecto

Para hacer que sea más fácil escribir configuraciones de registro personalizadas, la configuración de registro por defecto de Django ya no define los registradores django.request y django.security. En su lugar, define un único registrador django, filtrado a nivel INFO, con dos manejadores:

  • console: filtrado a nivel INFO y solo activo si DEBUG=True.

  • mail_admins: filtrado a nivel ERROR y solo activo si DEBUG=False.

Si no estás sobreescribiendo la configuración de registro de Django, deberías ver cambios mínimos en el comportamiento, pero podrías ver algún nuevo registro en la consola del servidor de ejecución, por ejemplo.

Si estás sobreescribiendo la configuración de registro de Django, debes comprobar cómo se combina tu configuración con los nuevos valores por defecto.

Los detalles de la solicitud HttpRequest en informes de errores

Fue redundante mostrar los detalles completos de la HttpRequest cada vez que aparecía como variable de marco de pila en la versión HTML de la página de depuración y el correo electrónico de error. Por lo tanto, la solicitud HTTP ahora muestra la misma representación estándar que otras variables (repr(request)). Como resultado, se eliminaron el método ExceptionReporterFilter.get_request_repr() y la función no documentada django.http.build_request_repr().

Se modificó el contenido de la versión de texto del correo electrónico para proporcionar un seguimiento de errores con la misma estructura que en el caso de solicitudes AJAX. Los detalles del seguimiento se renderizan mediante el método ExceptionReporter.get_traceback_text().

Eliminación de adaptadores y convertidores globales conscientes de zona horaria para fechas y horas

Django ya no registra adaptadores y convertidores globales para gestionar la información de la zona horaria en los valores datetime enviados a la base de datos como parámetros de consulta o leídos de la base de datos en resultados de consultas. Esta modificación afecta proyectos que cumplen con las siguientes condiciones:

  • La configuración USE_TZ es True.

  • La base de datos es SQLite, MySQL, Oracle u otra base de datos tercera parte que no soporta zonas horarias. Si tienes dudas, puedes comprobar el valor de connection.features.supports_timezones.

  • El código consulta la base de datos fuera del ORM, típicamente con cursor.execute(sql, params).

Si estás pasando parámetros datetime conscientes de zona horaria a tales consultas, debes convertirlos en fechas y horas ingenuas en UTC:

from django.utils import timezone

param = timezone.make_naive(param, timezone.utc)

Si no lo haces, la conversión se realizará como en versiones anteriores (con una advertencia de deprecación) hasta Django 1.11. Django 2.0 no realizará ninguna conversión, lo que puede provocar corrupción de datos.

Si estás leyendo valores de datetime desde los resultados, serán ingenuos en lugar de conscientes del tiempo. Puedes compensar como sigue:

from django.utils import timezone

value = timezone.make_aware(value, timezone.utc)

No necesitas nada de esto si estás consultando la base de datos a través del ORM, incluso si estás utilizando consultas raw(). El ORM se encarga de gestionar la información sobre la zona horaria.

Los módulos de etiquetas de plantilla se importan cuando las plantillas están configuradas

El backend DjangoTemplates ahora realiza descubrimiento en los módulos de etiquetas de plantilla instalados cuando se instancía. Esta actualización permite proporcionar bibliotecas explícitamente a través de la clave 'libraries' de OPTIONS al definir un backend DjangoTemplates. Los errores de importación o sintaxis en los módulos de etiquetas de plantilla ahora fallan temprano en el tiempo de instanciación en lugar de cuando se compila por primera vez una plantilla con la etiqueta {% load %}.

django.template.base.add_to_builtins() está eliminado

Aunque era una API privada, los proyectos comúnmente utilizaban add_to_builtins() para hacer disponibles las etiquetas y filtros de plantilla sin utilizar la etiqueta {% load %}. Esta API ha sido formalizada. Los proyectos deben definir bibliotecas integradas a través de la clave 'builtins' de OPTIONS al definir un backend DjangoTemplates.

simple_tag ahora envuelve el contenido de las etiquetas en conditional_escape

En general, las etiquetas de plantilla no autoescapan su contenido y este comportamiento está documentado. Para etiquetas como inclusion_tag, esto no es un problema porque la plantilla incluida realizará la autoescape. Para assignment_tag(), el contenido se escapará cuando se utilice como variable en la plantilla.

Para los casos de uso previstos para simple_tag, sin embargo, es muy fácil terminar con HTML incorrecto y posiblemente un exploit XSS. Por ejemplo:

@register.simple_tag(takes_context=True)
def greeting(context):
    return "Hello {0}!".format(context["request"].user.first_name)

En versiones antiguas de Django, esto será un problema XSS porque user.first_name no está escapado.

Los textos traducidos son:

Para corregir tus simple_tags, es mejor aplicar las siguientes prácticas:

  • Cualquier código que genere HTML debe utilizar el sistema de plantillas o format_html().

  • Si la salida de un simple_tag necesita escaparse, utiliza escape() o conditional_escape().

  • Si estás absolutamente seguro de que estás generando HTML desde una fuente confiable (por ejemplo, un campo de CMS que almacena HTML introducido por admins), puedes marcarlo como tal utilizando mark_safe().

Las etiquetas que siguen estas reglas serán correctas y seguras tanto si se ejecutan en Django 1.9+ o en versiones anteriores.

Paginator.page_range

Paginator.page_range ahora es un iterador en lugar de una lista.

En versiones de Django anteriores a 1.8, Paginator.page_range devolvía una list en Python 2 y un range en Python 3. Django 1.8 devolvió consistentemente una lista, pero un iterador es más eficiente.

El código existente que depende de características específicas de la lista, como el índice, se puede portar convirtiendo el iterador en una list utilizando list().

Implicit QuerySet __in lookup eliminado

En versiones anteriores, consultas como:

Model.objects.filter(related_id=RelatedModel.objects.all())

se convertían implícitamente a:

Model.objects.filter(related_id__in=RelatedModel.objects.all())

lo que resultaba en SQL como "related_id IN (SELECT id FROM ...)".

Esta consulta __in implícita ya no sucede, por lo que el «IN» SQL ahora es «=», y si la subconsulta devuelve múltiples resultados, al menos algunas bases de datos lanzarán un error.

Soporte del navegador para contrib.admin

El administrador ya no admite Internet Explorer 8 y versiones anteriores, ya que estos navegadores han alcanzado el fin de vida.

Se han eliminado los CSS e imágenes para soportar Internet Explorer 6 y 7. Los iconos PNG y GIF se han reemplazado con iconos SVG, que no están soportados por Internet Explorer 8 y versiones anteriores.

La biblioteca jQuery incorporada en el administrador ha sido actualizada desde la versión 1.11.2 a 2.1.4. jQuery 2.x tiene la misma API que jQuery 1.x, pero no admite Internet Explorer 6, 7 o 8, lo que permite una mejor rendimiento y un tamaño de archivo más pequeño. Si necesita soportar IE8 y también debe utilizar la última versión de Django, puede sobrescribir la copia del administrador de jQuery con su propia creando una aplicación Django con esta estructura:

app/static/admin/js/vendor/
    jquery.js
    jquery.min.js

Error SyntaxError al instalar Django setuptools 5.5.x

When instalando Django 1.9 o 1.9.1 con setuptools 5.5.x, verás:

Compiling django/conf/app_template/apps.py ...
  File "django/conf/app_template/apps.py", line 4
    class {{ camel_case_app_name }}Config(AppConfig):
          ^
SyntaxError: invalid syntax

Compiling django/conf/app_template/models.py ...
  File "django/conf/app_template/models.py", line 1
    {{ unicode_literals }}from django.db import models
                             ^
SyntaxError: invalid syntax

Es seguro ignorar estos errores (Django se instalará correctamente), pero puedes evitarlos actualizando setuptools a una versión más reciente. Si estás utilizando pip, puedes actualizar pip usando python -m pip install -U pip que también actualizará setuptools. Esto se resuelve en versiones posteriores de Django como se describe en la Notas de lanzamiento de Django 1.9.2.

Miscelánea

  • Los archivos estáticos jQuery en contrib.admin han sido movidos a un subdirectorio vendor/jquery.

  • El texto mostrado para columnas nulas en las celdas de list_display del panel de administración ha cambiado de (None) (o su equivalente traducido) a - (un guión).

  • django.http.responses.REASON_PHRASES y django.core.handlers.wsgi.STATUS_CODE_TEXT han sido eliminados. Utiliza la Biblioteca Estándar de Python en su lugar: http.client.responses para Python 3 y httplib.responses para Python 2.

  • ValuesQuerySet y ValuesListQuerySet han sido eliminados.

  • El template admin/base.html ya no establece window.__admin_media_prefix__ o window.__admin_utc_offset__. Las referencias de imágenes en JavaScript que utilizaban ese valor para construir URLs absolutas las han movido a CSS para una mayor personalización. El desplazamiento horario se almacena en un atributo de datos del tag <body>.

  • La validación del campo CommaSeparatedIntegerField ha sido refinada para prohibir valores como ',', ',1', y '1,,2'.

  • La inicialización de formularios se ha movido desde el método ProcessFormView.get() a la nueva método FormMixin.get_context_data(). Esto puede ser incompatibilidad hacia atrás si has sobrescrito el método get_context_data() sin llamar a super().

  • Se ha dejado de apoyar PostGIS 1.5.

  • El campo django.contrib.sites.models.Site.domain fue cambiado para ser unique.

  • Para garantizar la aislación de pruebas, se prohíben por defecto las consultas a la base de datos en las pruebas de SimpleTestCase. Puedes deshabilitar este comportamiento estableciendo el atributo de clase allow_database_queries a True en tu clase de prueba.

  • Se cambió ResolverMatch.app_name para que contenga la ruta del namespace completo en el caso de nombres de espacio anidados. Para consistencia con ResolverMatch.namespace, el valor vacío ahora es una cadena vacía en lugar de None.

  • Por razones de seguridad, las claves de sesión deben tener al menos 8 caracteres.

  • La función privada django.utils.functional.total_ordering() ha sido eliminada. Contenía un trabajo alrededor de una falla en functools.total_ordering() en versiones de Python anteriores a la 2.7.3.

  • La serialización XML (ya sea mediante dumpdata o el marco de syndication) utilizaba a producir cualquier carácter que recibiera. Ahora, si el contenido a ser serializado contiene caracteres de control no permitidos en la norma XML 1.0, la serialización fallará con un ValueError.

  • La clase CharField ahora elimina por defecto espacios en blanco en la entrada de inicio y fin. Esto se puede deshabilitar estableciendo el nuevo argumento strip a False.

  • El texto del template que es traducido y utiliza dos o más signos de porcentaje consecutivos, e.g. "%%", puede tener un nuevo msgid después de ejecutar makemessages (probablemente la traducción estará marcada como «fuzzy»). El nuevo msgid será marcado con "#, python-format".

  • Si no se establece ni request.current_app ni Context.current_app, el tag de plantilla url ahora utiliza el namespace del request actual. Establece request.current_app a None si no deseas utilizar una pista de nombre de espacio.

  • La configuración SILENCED_SYSTEM_CHECKS silencia ahora mensajes de todos los niveles. Anteriormente, se imprimían en la consola mensajes del nivel ERROR o superior.

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

  • El valor devuelto de setup_databases() y el primer argumento de teardown_databases() han cambiado. Anteriormente eran tuplas de la forma (old_names, mirrors). Ahora son solo el primer elemento, old_names.

  • Por defecto, LiveServerTestCase intenta encontrar un puerto disponible en el rango 8081-8179 en lugar de intentar únicamente el puerto 8081.

  • Las comprobaciones del sistema para ModelAdmin ahora verifican instancias en lugar de clases.

  • Se ha eliminado la API privada para aplicar planes de migración mixtos por razones de rendimiento. Los planes mixtos consisten en una lista de migraciones donde algunas se están aplicando y otras se están desaplicando.

  • Las clases de descriptor de objetos relacionados del modelo en django.db.models.fields.related (API privada) han sido movidas desde el módulo related a related_descriptors y renombradas como sigue:

    • ReverseSingleRelatedObjectDescriptor es ForwardManyToOneDescriptor

    • SingleRelatedObjectDescriptor es ReverseOneToOneDescriptor

    • ForeignRelatedObjectsDescriptor es ReverseManyToOneDescriptor

    • ManyRelatedObjectsDescriptor es ManyToManyDescriptor

  • Si implementas una vista personalizada handler404, debe devolver una respuesta con un código de estado HTTP 404. Utiliza HttpResponseNotFound o pasa status=404 a la HttpResponse. De lo contrario, APPEND_SLASH no funcionará correctamente con DEBUG=False.

Características obsoletas en 1.9

assignment_tag()

Django 1.4 agregó el asistente de ayuda assignment_tag para facilitar la creación de etiquetas de plantilla que almacenan resultados en una variable de plantilla. El ayudante simple_tag() ha ganado esta misma capacidad, lo que hace que assignment_tag sea obsoleto. Las etiquetas que utilizan assignment_tag deben actualizarse para utilizar simple_tag.

Sintaxis {% cycle %} con argumentos separados por comas

La etiqueta cycle admite una antigua sintaxis inferior de versiones anteriores de Django:

{% cycle row1,row2,row3 %}

Su parsing causó errores con la sintaxis actual, por lo que se eliminará el soporte para la antigua sintaxis en Django 1.10 siguiendo un desplazamiento acelerado.

ForeignKey y OneToOneField argumento on_delete

Para aumentar la conciencia sobre la eliminación cascada de modelos, el argumento on_delete de ForeignKey y OneToOneField será obligatorio en Django 2.0.

Actualiza los modelos y las migraciones existentes para establecer explícitamente el argumento. Dado que el valor por defecto es models.CASCADE, agrega on_delete=models.CASCADE a todos los ForeignKey y OneToOneField que no utilicen una opción diferente. También puedes pasarla como segundo argumento posicional si no te importa la compatibilidad con versiones antiguas de Django.

Los cambios en Field.rel

Los cambios en Field.rel y sus métodos y atributos han sido realizados para coincidir con la API de campos relacionados. El atributo Field.rel ha sido renombrado a remote_field y muchos de sus métodos y atributos han cambiado o han sido renombrados.

El objetivo de estos cambios es proporcionar una API documentada para los campos de relación.

Métodos personalizados de GeoManager y GeoQuerySet

Todos los métodos personalizados de GeoQuerySet (area(), distance(), gml(), …) han sido reemplazados por expresiones geográficas equivalentes en anotaciones (consulte las nuevas características). Por lo tanto, la necesidad de establecer un GeoManager personalizado para modelos GIS ya no es obligatoria. Tan pronto como tu código no llame a ninguno de los métodos obsoletos, puedes simplemente eliminar las líneas objects = GeoManager() de tus modelos.

Cambios en la API de cargadores de plantillas

Los cargadores de plantillas Django han sido actualizados para permitir el extensión de plantillas recursiva. Este cambio requirió una nueva API de cargador de plantillas. Los métodos load_template() y load_template_sources() anteriores ahora están descontinuados. Puedes encontrar detalles sobre la nueva API en la documentación del cargador de plantillas en la documentación del cargador de plantillas.

Pasando un 3-tupla o una cadena app_name a include()

La parte del espacio de nombres de instancia al pasar un tupla como argumento a include() ha sido reemplazada por pasar el argumento namespace a include(). Por ejemplo:

polls_patterns = [
    url(...),
]

urlpatterns = [
    url(r"^polls/", include((polls_patterns, "polls", "author-polls"))),
]

become

polls_patterns = (
    [
        url(...),
    ],
    "polls",
)  # 'polls' is the app_name

urlpatterns = [
    url(r"^polls/", include(polls_patterns, namespace="author-polls")),
]

El argumento app_name a include() ha sido reemplazado por pasar una 2-tupla (como arriba), o pasando un objeto o módulo con un atributo app_name, como se muestra a continuación. Si el app_name está configurado de esta manera nueva, el argumento namespace ya no es necesario. Se establecerá por defecto en el valor de app_name. Por ejemplo, los patrones de URL en la guía del tutorial han sido cambiados desde:

mysite/urls.py
urlpatterns = [url(r"^polls/", include("polls.urls", namespace="polls")), ...]

:to:``

mysite/urls.py
urlpatterns = [
    url(r"^polls/", include("polls.urls")),  # 'namespace="polls"' removed
    ...,
]
polls/urls.py
app_name = "polls"  # added
urlpatterns = [...]

Esta modificación también significa que la forma antigua de incluir una instancia de AdminSite está desaconsejada. En su lugar, pasa admin.site.urls directamente a django.conf.urls.url():

urls.py
from django.conf.urls import url
from django.contrib import admin

urlpatterns = [
    url(r"^admin/", admin.site.urls),
]

Nombre de espacio de aplicación requerido si se establece un nombre de espacio de instancia

En el pasado, un espacio de nombres de instancia sin un espacio de nombres de aplicación serviría con el mismo propósito que el espacio de nombres de aplicación, pero era imposible revertir los patrones si había un espacio de nombres de aplicación con el mismo nombre. Las inclusiones que especifican un espacio de nombres de instancia requieren que la URLconf incluida establezca un espacio de nombres de aplicación.

parametro actual_app al contrib.auth vistas

Todas las vistas en django.contrib.auth.views tienen la siguiente estructura:

def view(request, ..., current_app=None, ...):

    ...

    if current_app is not None:
        request.current_app = current_app

    return TemplateResponse(request, template_name, context)

A partir de Django 1.8, current_app se establece en el objeto request. Para la consistencia, estas vistas requerirán que el llamador establezca current_app en el request en lugar de pasarla como un argumento separado.

django.contrib.gis.geoip

El módulo django.contrib.gis.geoip2 sustituye a django.contrib.gis.geoip. El nuevo módulo proporciona una API similar, excepto que no proporciona métodos de compatibilidad con la API GeoIP-Python legada.

Miscelánea

  • El argumento weak en django.dispatch.signals.Signal.disconnect() ha sido descontinuado ya que no tiene efecto alguno.

  • La método check_aggregate_support() de django.db.backends.base.BaseDatabaseOperations ha sido descontinuado y será eliminado en Django 2.0. Se debe utilizar el más general check_expression_support() en su lugar.

  • django.forms.extras está descontinuada. Puedes encontrar SelectDateWidget en django.forms.widgets (o simplemente django.forms) en su lugar.

  • La API privada django.db.models.fields.add_lazy_relation() ha sido descontinuada.

  • El decorador de la función @skipIfCustomUser de django.contrib.auth.tests.utils está descontinuado. Con los cambios de descubrimiento de pruebas en Django 1.6, las pruebas para aplicaciones de django.contrib ya no se ejecutan como parte del proyecto del usuario. Por lo tanto, el decorador @skipIfCustomUser ya no es necesario para decorar pruebas en django.contrib.auth.

  • Si personalizaste algunos manejadores de errores, las firmas de vistas con solo un parámetro de solicitud están descontinuadas. Las vistas deben aceptar ahora también un segundo parámetro posicional exception.

  • Los atributos django.utils.feedgenerator.Atom1Feed.mime_type y django.utils.feedgenerator.RssFeed.mime_type están descontinuados a favor de content_type.

  • Signer ahora emite una advertencia si se utiliza un separador inválido. Esto se convertirá en una excepción en Django 1.10.

  • django.db.models.Field._get_val_from_obj() está descontinuado en favor de Field.value_from_object().

  • django.template.loaders.eggs.Loader está descontinuado ya que se recomienda no distribuir aplicaciones como huevos.

  • La argumento de palabra clave callable_obj a SimpleTestCase.assertRaisesMessage() está descontinuado. Pasa el llamable como un argumento posicional en su lugar.

  • La atributo allow_tags en los métodos de ModelAdmin ha sido descontinuado. Utiliza format_html(), format_html_join() o mark_safe() al construir el valor de retorno del método en su lugar.

  • El argumento de palabra clave enclosure a SyndicationFeed.add_item() está descontinuado. Utiliza el nuevo argumento enclosures que acepta una lista de objetos Enclosure en lugar de uno solo.

  • Las alias django.template.loader.LoaderOrigin y django.template.base.StringOrigin para django.template.base.Origin están descontinuados.

Características eliminadas en 1.9

Estas características han llegado al final de su ciclo de descontinuación y se eliminan en Django 1.9. Consulte Características deprecadas en 1.7 para detalles, incluyendo cómo eliminar el uso de estas características.

  • django.utils.dictconfig está eliminado.

  • django.utils.importlib está eliminado.

  • django.utils.tzinfo se ha eliminado.

  • django.utils.unittest se ha eliminado.

  • La orden syncdb se ha eliminado.

  • Se han eliminado django.db.models.signals.pre_syncdb y django.db.models.signals.post_syncdb.

  • Se ha eliminado el soporte para allow_syncdb en los routers de bases de datos.

  • La sincronización automática de aplicaciones sin migraciones se ha eliminado. Las migraciones son obligatorias para todas las aplicaciones a menos que pases la opción migrate --run-syncdb.

  • Las órdenes SQL de gestión para aplicaciones sin migraciones, sql, sqlall, sqlclear, sqldropindexes y sqlindexes, se han eliminado.

  • Se ha eliminado el soporte para la carga automática de fijos de datos iniciales initial_data y datos SQL iniciales.

  • Todos los modelos deben estar definidos dentro de una aplicación instalada o declarar un etiqueta explícita app_label. Además, no es posible importarlos antes de que su aplicación esté cargada. En particular, no es posible importar modelos dentro del paquete raíz de una aplicación.

  • El modelo y la forma IPAddressField se han eliminado. Un campo stub permanece por compatibilidad con migraciones históricas.

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

  • RequestSite y get_current_site() ya no son importables desde django.contrib.sites.models.

  • El soporte para FastCGI a través de la orden de comando runfcgi se ha eliminado.

  • django.utils.datastructures.SortedDict se ha eliminado.

  • ModelAdmin.declared_fieldsets se ha eliminado.

  • Los módulos util que proporcionaban compatibilidad hacia atrás han sido eliminados:

    • django.contrib.admin.util

    • django.contrib.gis.db.backends.util

    • django.db.backends.util

    • django.forms.util

  • ModelAdmin.get_formsets se ha eliminado.

  • Las shims de compatibilidad hacia atrás introducidas para renombrar el método BaseMemcachedCache._get_memcache_timeout() a get_backend_timeout() han sido eliminadas.

  • Las opciones --natural y -n para dumpdata se han eliminado.

  • El argumento use_natural_keys para serializers.serialize() se ha eliminado.

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

  • Se ha eliminado la capacidad de utilizar un SplitDateTimeWidget con DateTimeField.

  • La propiedad WSGIRequest.REQUEST está eliminada.

  • La clase django.utils.datastructures.MergeDict está eliminada.

  • Los códigos de idioma zh-cn y zh-tw están eliminados.

  • Se ha eliminado la función interna django.utils.functional.memoize().

  • django.core.cache.get_cache está eliminado.

  • django.db.models.loading está eliminada.

  • Ya no es posible pasar argumentos llamables a consultas de conjuntos de datos.

  • Se ha eliminado BaseCommand.requires_model_validation en favor de requires_system_checks. Los validadores de administración se reemplazan por comprobaciones de administración.

  • Los textos traducidos son:

  • La función ModelAdmin.validate() está eliminada.

  • La función django.db.backends.DatabaseValidation.validate_field está eliminada en favor de la función check_field.

  • El comando de gestión validate está eliminado.

  • La función django.utils.module_loading.import_by_path está eliminada en favor de django.utils.module_loading.import_string.

  • Las etiquetas de plantilla ssi y url están eliminadas del biblioteca de etiquetas de plantilla future.

  • La función django.utils.text.javascript_quote() está eliminada.

  • Los ajustes de prueba de base de datos como entradas independientes en los ajustes de la base de datos, prefijados con TEST_, ya no están soportados.

  • La opción cache_choices para ModelChoiceField y ModelMultipleChoiceField está eliminada.

  • El valor por defecto de la propiedad RedirectView.permanent ha cambiado de True a False.

  • La clase django.contrib.sitemaps.FlatPageSitemap ha sido eliminada en favor de django.contrib.flatpages.sitemaps.FlatPageSitemap.

  • Se ha eliminado la API privada django.test.utils.TestTemplateLoader.

  • El módulo django.contrib.contenttypes.generic ha sido eliminado.