2 de diciembre de 2019
Bienvenido a Django 3.0!
Estas notas de lanzamiento cubren las nuevas características, así como algunos cambios que no son compatibles con la versión anterior que debes tener en cuenta al actualizar desde Django 2.2 o una versión anterior. 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-3.0>.
Consulte la guía Cómo actualizar Django a una versión más reciente si estás actualizando un proyecto existente.
Django 3.0 admite Python 3.6, 3.7, 3.8 y 3.9 (a partir de 3.0.11). Muy recomendamos y solo oficialmente apoyamos la última versión de cada serie.
La serie Django 2.2.x es la última que admite Python 3.5.
Después del lanzamiento de Django 3.0, sugerimos a los autores de aplicaciones terceras que abandonen el soporte para todas las versiones de Django anteriores a 2.2. En ese momento, deberías poder ejecutar las pruebas de tu paquete utilizando python -Wd para que las advertencias de deprecación aparezcan. Después de hacer los ajustes de advertencia de deprecación, tu aplicación debe ser compatible con Django 3.0.
Django ahora oficialmente admite MariaDB 10.1 y superior. Consulte Notas de MariaDB para obtener más detalles.
Django 3.0 comienza nuestro viaje a hacer que Django sea completamente capaz de ejecutarse de manera asíncrona proporcionando soporte para ejecutar como una aplicación ASGI.
Esto se suma al soporte WSGI existente. Django tiene la intención de admitir ambos en el futuro previsible. Las características asíncronas solo estarán disponibles para aplicaciones que ejecuten bajo ASGI, sin embargo.
En este momento, el soporte asíncrono solo se aplica a la aplicación ASGI externa. Internamente todo sigue siendo sincrónico. El middleware asíncrono, vistas, etc., no están aún admitidos. Sin embargo, puedes utilizar middleware ASGI alrededor de la aplicación de Django, lo que te permite combinar Django con otros frameworks ASGI.
No hay necesidad de cambiar tus aplicaciones a menos que quieras empezar a experimentar con código asíncrono, pero tenemos documentación sobre la depuración con ASGI si quieres aprender más.
Ten en cuenta que como efecto secundario de esta modificación, Django ahora está consciente de los bucles de eventos asíncronos y bloqueará tu código marcado como «inseguro para llamadas asíncronas» - como operaciones ORM - desde un contexto asíncrono. Si estabas utilizando Django desde código asíncrono antes, esto puede desencadenar si lo hacías incorrectamente. Si ves un error SynchronousOnlyOperation, entonces examina de cerca tu código y mueve cualquier operación de base de datos a una subhilo sincrónica.
La traducción de los textos es la siguiente:
Las expresiones que devuelven ~django.db.models.BooleanField pueden utilizarse directamente en filtros de QuerySet, sin tener que anotar y luego filtrar contra la anotación.
Los tipos personalizados de enumeración TextChoices, IntegerChoices y Choices están disponibles como una forma de definir Field.opciones. Los tipos TextChoices y IntegerChoices se proporcionan para campos de texto e integer. La clase Choices permite definir una enumeración compatible con otros tipos de datos concretos. Estos tipos personalizados de enumeración admiten etiquetas legibles por humanos que pueden ser traducidas y accedidas a través de una propiedad en la enumeración o sus miembros. Consulte Tipos de enumeración para obtener más detalles y ejemplos.
django.contrib.admin¶Se ha agregado soporte para la atributo admin_order_field en propiedades en ModelAdmin.list_display.
La nueva método ModelAdmin.get_inlines() <django.contrib.admin.ModelAdmin.get_inlines> permite especificar las líneas basadas en la solicitud o instancia de modelo.
La biblioteca Select2 se ha actualizado desde la versión 4.0.3 a 4.0.7.
jQuery se ha actualizado desde la versión 3.3.1 a 3.4.1.
django.contrib.auth¶El nuevo atributo reset_url_token en PasswordResetConfirmView permite especificar un parámetro de token que se muestra como componente de las URLs de restablecimiento de contraseña.
Se han agregado la clase BaseBackend para facilitar la personalización de los backends de autenticación.
Se ha agregado el método get_user_permissions() para reflejar el método existente get_group_permissions().
Se ha agregado la atributo autocomplete HTML a los widgets de campos de usuario, correo electrónico y contraseña en django.contrib.auth.forms para una mejor interacción con los administradores de contraseñas del navegador.
El comando createsuperuser ahora utiliza las variables de entorno para la contraseña y los campos requeridos cuando no se proporciona el argumento correspondiente en modo no interactivo.
La propiedad REQUIRED_FIELDS ahora admite relaciones muchos a muchos con ManyToManyField.
El nuevo método UserManager.with_perm() devuelve los usuarios que tienen la permiso especificado.
Se ha aumentado el recuento de iteraciones por defecto para el algoritmo de hash de contraseña PBKDF2 de 150,000 a 180,000.
django.contrib.gis¶Se han permitido las funciones de búsqueda espacial MySQL para operar con geometrías reales. El soporte anterior estaba limitado a cajas de enfoque.
Se ha agregado la función GeometryDistance, que está disponible en PostGIS.
Se ha agregado el soporte para la unidad furlong en Distance.
La traducción de los textos es la siguiente:
La clase GeoIP2 ahora acepta pathlib.Path path.
django.contrib.postgres¶La nueva clase RangeOperators ayuda a evitar los errores de tipeo en operadores SQL que se pueden utilizar conjuntamente con RangeField.
La nueva expresión RangeBoundary representa las fronteras del rango.
Las nuevas clases AddIndexConcurrently y RemoveIndexConcurrently permiten crear e eliminar índices CONCURRENTLY en PostgreSQL.
django.contrib.sesiones¶El nuevo método get_session_cookie_age() permite especificar dinámicamente la edad de la cookie de sesión.
Las funciones add_never_cache_headers() y never_cache() ahora agregan la directiva private a los encabezados Cache-Control.
El nuevo método Storage.get_alternative_name() permite personalizar el algoritmo para generar nombres de archivo si ya existe un archivo con el nombre subido original.
Los formularios pueden controlar el widget utilizado cuando se ordenan los formularios mediante la propiedad can_order estableciendo la propiedad ordering_widget o sobrescribiendo el método get_ordering_widget().
Se han agregado las configuraciones LANGUAGE_COOKIE_HTTPONLY, LANGUAGE_COOKIE_SAMESITE y LANGUAGE_COOKIE_SECURE para establecer las banderas HttpOnly, SameSite y Secure en los cookies de idioma. Los valores predeterminados de estas configuraciones preservan el comportamiento anterior.
Se ha agregado soporte y traducciones para el idioma uzbeko.
El nuevo parámetro reporter_class de AdminEmailHandler permite proporcionar una subclase de django.views.debug.ExceptionReporter para personalizar el texto del seguimiento enviado al sitio ADMINS cuando DEBUG es False.
La nueva opción compilemessages --ignore permite ignorar directorios específicos al buscar archivos .po para compilar.
showmigrations --list ahora muestra las fechas de aplicación cuando --verbosity es 2 y superior.
En PostgreSQL, dbshell ahora admite certificados TLS del lado del cliente.
inspectdb ahora introspecta OneToOneField cuando una clave foránea tiene una restricción de clave única o primaria.
La nueva opción --skip-checks omite la ejecución de comprobaciones del sistema antes de ejecutar el comando.
Las opciones startapp --template y startproject --template ahora admiten plantillas almacenadas en archivos XZ (.tar.xz, .txz) y LZMA (.tar.lzma, .tlz).
Se han agregado funciones de base de datos hash: MD5, SHA1, SHA224, SHA256, SHA384 y SHA512.
Se han agregado la función de base de datos Sign.
La nueva parámetro is_dst del las funciones de base de datos Trunc determina el tratamiento de los datetimes inexistentes y ambiguos.
connection.queries ahora muestra las sentencias COPY … TO en PostgreSQL.
FilePathField ahora acepta una función llamable para path.
Se ha permitido la tabla intermedia simétrica para las relaciones de muchos a muchos ManyToManyField.
Los atributos name de CheckConstraint, UniqueConstraint y Index ahora admiten la interpolación del etiqueta de aplicación y clase utilizando los lugares de sustitución '%(app_label)s' y '%(class)s'.
La nueva atributo Field.descriptor_class permite a los campos de modelo personalizar el comportamiento get y set sobreescribiendo sus descriptores.
Se ha agregado SmallAutoField, que actúa mucho como un AutoField excepto que solo permite valores bajo cierto (dependiente de la base de datos) límite. Los valores desde 1 a 32767 son seguros en todas las bases de datos admitidas por Django.
AutoField, BigAutoField y SmallAutoField ahora heredan de IntegerField, BigIntegerField y SmallIntegerField respectivamente. Los controles de sistema y validadores se heredan también correctamente.
FileField.upload_to ahora admite pathlib.Path.
CheckConstraint está ahora soportado en MySQL 8.0.16+.
La nueva allows_group_by_selected_pks_on_model() método de django.db.backends.base.BaseDatabaseFeatures permite la optimización de las cláusulas GROUP BY para que requieran solo los clave primarias seleccionadas de los modelos. Por defecto, está soportado sólo para modelos administrados en PostgreSQL.
Para habilitar la optimización de cláusulas GROUP BY con clave primaria única para modelos no administrados, debes heredar la base del motor de bases de datos PostgreSQL, sobrescribiendo la clase de características allows_group_by_selected_pks_on_model() como requieras. Consulta Herencia de los motores de bases de datos integrados para un ejemplo.
Se permite a HttpResponse ser inicializado con contenido de memoryview.
Para su uso en, por ejemplo, plantillas Django, HttpRequest.headers ahora admite consultas utilizando guiones bajos (por ejemplo user_agent) en lugar de guiones.
X_FRAME_OPTIONS ahora tiene como valor predeterminado 'DENY'. En versiones anteriores, el parámetro X_FRAME_OPTIONS tiene como valor predeterminado 'SAMEORIGIN'. Si tu sitio utiliza marcos de sí mismo, necesitarás establecer explícitamente X_FRAME_OPTIONS = 'SAMEORIGIN' para que sigan funcionando.
SECURE_CONTENT_TYPE_NOSNIFF ahora tiene como valor predeterminado True. Con esto habilitado, SecurityMiddleware establece el encabezado X-Content-Type-Options: nosniff en todas las respuestas que no lo tengan ya.
SecurityMiddleware puede enviar ahora el encabezado Referrer-Policy.
El nuevo argumento de prueba Client raise_request_exception permite controlar si las excepciones levantadas durante la solicitud también deben ser levantadas en la prueba. El valor predeterminado es True para compatibilidad hacia atrás. Si es False y ocurre una excepción, el cliente de pruebas devolverá una respuesta 500 con el atributo exc_info, un tupla que proporciona información sobre la excepción que ocurrió.
Pruebas y casos de prueba para ejecutar pueden ser seleccionadas por patrón de nombre de prueba utilizando la nueva opción test -k.
Comparación de HTML, tal como se utiliza en assertHTMLEqual(), ahora considera que el texto, las referencias a caracteres y las referencias a entidades que se refieren al mismo carácter son equivalentes.
DiscoverRunner puede generar ahora un depurador en cada error o falla utilizando la opción test --pdb.
Model.save() ya no intenta encontrar una fila cuando se guarda una instancia nueva de Model y se proporciona un valor por defecto para la clave primaria, y siempre realiza una consulta INSERT única. En versiones antiguas de Django, Model.save() realizaba una consulta INSERT o UPDATE según si existía la fila.
Llama a Model.save() mientras se proporciona un valor de clave primaria por defecto equivalente a pasar force_insert=True al método save() del modelo. Los intentos de utilizar una nueva instancia de Model para actualizar una fila existente darán como resultado un error de integridad IntegrityError.
Para actualizar un modelo existente para un valor de clave primaria específico, utilice el método update_or_create() o QuerySet.filter(pk=…).update(…) en su lugar. Por ejemplo:
>>> MyModel.objects.update_or_create(pk=existing_pk, defaults={"name": "new name"})
>>> MyModel.objects.filter(pk=existing_pk).update(name="new name")
Esta es la traducción de los textos:
La segunda argumento de DatabaseIntrospection.get_geometry_type() es ahora la descripción de fila en lugar del nombre de columna.
DatabaseIntrospection.get_field_type() puede dejar de devolver tuplas.
Si la base de datos puede crear claves foráneas en el mismo statement SQL que agrega un campo, agregue SchemaEditor.sql_create_column_inline_fk con el SQL apropiado; de lo contrario, establezca DatabaseFeatures.can_create_inline_fk = False.
DatabaseFeatures.can_return_id_from_insert y can_return_ids_from_bulk_insert se renombran a can_return_columns_from_insert y can_return_rows_from_bulk_insert.
Las funciones de la base de datos ahora manejan formatos datetime.timezone cuando se crean utilizando instancias de datetime.timedelta (por ejemplo, timezone(timedelta(hours=5)), que produciría 'UTC+05:00'). Los backends tercerizados deben manejar este formato cuando preparen DateTimeField en datetime_cast_date_sql(), datetime_extract_sql(), etc.
Se agregan entradas para AutoField, BigAutoField y SmallAutoField a DatabaseOperations.integer_field_ranges para apoyar los validadores de rango de números enteros en estos tipos de campo. Los backends tercerizados pueden necesitar personalizar las entradas predeterminadas.
DatabaseOperations.fetch_returned_insert_id() se reemplaza por fetch_returned_insert_columns(), que devuelve una lista de valores devueltos por el statement INSERT … RETURNING, en lugar de un valor único.
DatabaseOperations.return_insert_id() se reemplaza por return_insert_columns(), que acepta un argumento fields, que es un iterable de campos a ser devueltos después del insert. Normalmente, esto solo es la clave primaria auto-generada.
django.contrib.admin¶Los mensajes de cambio en el historial de modelos de Admin ahora prefieren etiquetas de campo más legibles en lugar de nombres de campo.
django.contrib.gis¶Se elimina el soporte para PostGIS 2.1.
Se elimina el soporte para SpatiaLite 4.1 y 4.2.
Supporto para GDAL 1.11 y GEOS 3.4 se ha eliminado.
El soporte upstream para PostgreSQL 9.4 finaliza en diciembre del 2019. Django 3.0 admite PostgreSQL 9.5 y versiones superiores.
El soporte upstream para Oracle 12.1 finaliza en julio del 2021. Django 2.2 seguirá siendo compatible hasta abril del 2022. Django 3.0 admite oficialmente Oracle 12.2 y 18c.
Aunque el soporte para Python 2 se eliminó en Django 2.0, algunas APIs privadas no se eliminaron de Django para que las aplicaciones terceras pudieran seguir utilizandolas hasta la finalización del ciclo de vida de Python 2.
Dado que esperamos que las aplicaciones eliminen la compatibilidad con Python 2 cuando agreguen soporte a Django 3.0, estamos eliminando estas API en este momento.
django.test.utils.str_prefix() - Las cadenas no tienen prefijos “u” en Python 3.
django.test.utils.patch_logger() - Utiliza unittest.TestCase.assertLogs() en su lugar.
django.utils.lru_cache.lru_cache() - Alias de functools.lru_cache().
django.utils.decorators.available_attrs() - Esta función devuelve functools.WRAPPER_ASSIGNMENTS.
django.utils.decorators.ContextDecorator - Alias de contextlib.ContextDecorator.
django.utils._os.abspathu() - Alias de os.path.abspath().
django.utils._os.upath() y npath() - Estas funciones no hacen nada en Python 3.
django.utils.six - Elimina el uso de esta biblioteca vendida o cambia a six.
django.utils.encoding.python_2_unicode_compatible() - Alias de six.python_2_unicode_compatible().
django.utils.functional.curry() - Utiliza functools.partial() o functools.partialmethod. Consulta 5b1c389603a353625ae1603ba345147356336afb.
django.utils.safestring.SafeBytes - No utilizada desde Django 2.0.
FILE_UPLOAD_PERMISSIONS¶Los textos traducidos son:
Ahora FILE_UPLOAD_PERMISSIONS tiene como valor por defecto 0o644 para evitar esta inconsistencia.
Para hacer que los proyectos Django sean más seguros por defecto, algunas configuraciones de seguridad tienen ahora valores por defecto más seguros:
X_FRAME_OPTIONS ahora tiene como valor por defecto 'DENY'.
SECURE_CONTENT_TYPE_NOSNIFF ahora tiene como valor por defecto True.
Consulte la sección Qué hay de nuevo de seguridad anterior para obtener más detalles sobre estos cambios.
Ahora ContentType.__str__() incluye el etiqueta de aplicación del modelo para desambiguar modelos con el mismo nombre en diferentes aplicaciones.
Dado que acceder al idioma en la sesión en lugar de en el cookie está deprecado, LocaleMiddleware ya no busca el idioma del usuario en la sesión y django.contrib.auth.logout() ya no conserva el idioma de la sesión después de cerrar sesión.
django.utils.html.escape() ahora utiliza html.escape() para escapar HTML. Esto convierte ' a ' en lugar del código decimal equivalente anterior '.
The django-admin test -k option now works as the unittest -k option rather que como un atajo para --keepdb.
Se ha eliminado el soporte para pywatchman < 1.2.0.
urlencode() ahora codifica los valores iterables tal y como lo hacen cuando doseq=False, en lugar de iterarlos, lo que lo pone en línea con la función estándar urllib.parse.urlencode().
El filtro de plantilla intword ahora traduce 1.0 como una frase singular y todos los demás valores numéricos como plurales. Esto puede ser incorrecto para algunos idiomas.
Asignar un valor a la propiedad “_id” de un modelo ForeignKey o OneToOneField ahora desactiva el campo correspondiente. Acceder al campo después resultará en una consulta.
patch_vary_headers() ahora maneja un asterisco '*' según la especificación RFC 7231 Section 7.1.4, es decir, si una lista de nombres de campos de encabezado contiene un asterisco, entonces el encabezado Vary consistirá en un solo asterisco '*'.
En MySQL 8.0.16+, PositiveIntegerField y PositiveSmallIntegerField ahora incluyen una restricción de verificación para prevenir valores negativos en la base de datos.
Se ha agregado alias=None a la firma de Expression.get_group_by_cols().
RegexPattern, utilizado por re_path(), ya no devuelve argumentos clave con valores None para pasar a la vista para los grupos nombrados opcionales que faltan.
django.utils.encoding.force_text() y smart_text()¶Las alias smart_text() y force_text() (desde Django 2.0) de smart_str() y force_str() están descontinuadas. Ignora esta descontinuación si tu código soporta Python 2, ya que el comportamiento de smart_str() y force_str() es diferente allí.
django.utils.http.urlquote(), urlquote_plus(), urlunquote(), y urlunquote_plus() están descontinuados en favor de las funciones a las que son alias: urllib.parse.quote(), quote_plus(), unquote(), y unquote_plus().
django.utils.translation.ugettext(), ugettext_lazy(), ugettext_noop(), ungettext(), y ungettext_lazy() están descontinuados en favor de las funciones a las que son alias: django.utils.translation.gettext(), gettext_lazy(), gettext_noop(), ngettext(), y ngettext_lazy().
Para limitar la creación de sesiones y favorecer algunas estrategias de caché, django.views.i18n.set_language() dejará de establecer el idioma del usuario en la sesión en Django 4.0. Desde Django 2.1, el idioma se almacena siempre en el cookie LANGUAGE_COOKIE_NAME.
django.utils.text.unescape_entities() está descontinuado en favor de html.unescape(). Ten en cuenta que a diferencia de unescape_entities(), html.unescape() evalúa las cadenas lazy inmediatamente.
Para evitar posibles confusiones sobre el alcance efectivo, la utilidad interna privada is_safe_url() se renombró a url_has_allowed_host_and_scheme(). Que una URL tenga un host y esquema permitidos no implica en general que sea «segura». Puede estar aún mal citada, por ejemplo. Asegúrate de utilizar también iri_to_uri() en el componente de ruta de las URLs no confiables.
Estas características han alcanzado el final de su ciclo de descontinuación y se eliminan en Django 3.0.
Consulta Características obsoletas en 2.0 para obtener detalles sobre estas modificaciones, incluyendo cómo eliminar el uso de estas características.
El módulo django.db.backends.postgresql_psycopg2 se ha eliminado.
Se ha eliminado la función render_to_response() de django.shortcuts.
La configuración DEFAULT_CONTENT_TYPE se ha eliminado.
Se ha eliminado el método xreadlines() de HttpRequest.
Se ha eliminado el soporte para el argumento context de Field.from_db_value() y Expression.convert_value().
Se ha eliminado el argumento field_name de QuerySet.earliest() y latest().
Consulte la sección Características deprecadas en 2.1. para obtener detalles sobre estas modificaciones, incluyendo cómo eliminar el uso de estas características.
La función GIS ForceRHR se ha eliminado.
Se ha eliminado la función cookie_date() de django.utils.http.
Las bibliotecas de etiquetas de plantilla staticfiles y admin_static se han eliminado.
django.contrib.staticfiles.templatetags.staticfiles.static() se ha eliminado.
may 31, 2026