2 décembre 2019
Bienvenue dans Django 3.0 !
Ces notes de publications couvrent les nouvelles fonctionnalités, ainsi que certaines modifications non rétro-compatibles dont il faut être au courant lors la mise à jour depuis Django 2.2 ou des versions plus anciennes. Nous avons abandonné certaines fonctionnalités qui ont atteint la fin de leur cycle d’obsolescence et nous avons commencé le processus d’obsolescence de certaines fonctionnalités.
Voir le guide Mise à jour de Django à une version plus récente si vous mettez à jour un projet existant.
Django 3.0 requiert Python 3.6, 3.7 ou 3.8. Nous recommandons vivement et nous ne prenons officiellement en charge que la dernière publication de chaque série.
La série Django 2.2.x est la dernière à prendre en charge Python 3.5.
Après la publication de Django 3.0, nous suggérons aux applications tierces de ne plus prendre en charge les versions de Django plus anciennes que 2.2. À ce moment, vous devriez pouvoir exécuter les tests de votre projet en utilisant python -Wd afin de faire apparaître les avertissements d’obsolescence. Après avoir corrigé ceux-ci, votre application devrait être compatible avec Django 3.0.
Django prend dorénavant officiellement en charge MariaDB 10.1 ou plus récent. Lisez les notes MariaDB pour plus de détails.
Django 3.0 commence le voyage vers la fonctionnalité asynchrone de Django en fournissant la prise en charge de l’exécution d’applications ASGI.
Il s’agit d’un ajout en plus de la prise en charge existante du protocole WSGI. Django prévoit de prendre en charge les deux à l’avenir. Les fonctionnalités asychrones ne seront toutefois disponibles que pour les applications fonctionnant avec ASGI.
At this stage async support only applies to the outer ASGI application. Internally everything remains synchronous. Asynchronous middleware, views, etc. are not yet supported. You can, however, use ASGI middleware around Django’s application, allowing you to combine Django with other ASGI frameworks.
Aucun besoin de convertir vos applications sauf si vous souhaitez expérimenter avec du code asynchrone ; si vous souhaitez en savoir plus, vous pouvez lire la documentation sur le déploiement avec ASGI.
Notez qu’un effet de bord de cette nouveauté est que Django sait maintenant détecter des boucles événementielles asynchrones et vous empêchera d’appeler du code marqué comme non adapté à l’asynchrone (« async unsafe »), tel que des opérations avec l’ORM, à partir d’un contexte asynchrone. Si vous utilisiez précédemment Django à partir de code asynchrone, ceci pourrait vous bloquer si vous ne le faisiez pas correctement. Si vous voyez une erreur SynchronousOnlyOperation
, examinez attentivement votre code et déplacez d’éventuelles opérations de base de données plutôt dans un fil d’exécution synchrone.
La nouvelle classe ExclusionConstraint
permet d’ajouter des contraintes d’exclusion avec PostgreSQL Ces contraintes peuvent être ajoutées aux modèles en utilisant l’option Meta.constraints
.
Les expressions qui produisent des résultats BooleanField
peuvent dorénavant être directement utilisées dans des filtres QuerySet
, sans devoir passer par une annotation préalable et un filtre sur cette annotation.
Les types d’énumération personnalisés TextChoices
, IntegerChoices
et Choices
sont dorénavant disponibles dans l’optique de définir Field.choices
. Les types TextChoices
et IntegerChoices
sont fournis pour les champs texte et nombre entier. La classe Choices
permet de définir une énumération compatible avec les autres types de données concrets. Ces types personnalisés prennent en charge les étiquettes conviviales pouvant être traduites et obtenues par une propriété de l’énumération ou de ses membres. Lisez Types énumératifs pour plus de détails et des exemples.
django.contrib.admin
¶admin_order_field
pour les propriétés dans ModelAdmin.list_display
.ModelAdmin.get_inlines()
permet de définir les sous-formulaires intégrés sur la base de la requête ou de l’instance de modèle.django.contrib.auth
¶reset_url_token
dans PasswordResetConfirmView
permet de définir un paramètre jeton affiché comme composant des URL de réinitialisation de mot de passe.BaseBackend
a été ajoutée pour faciliter la personnalisation des moteurs d’authentification.get_user_permissions()
a été ajoutée pour faire écho à la méthode existante get_group_permissions()
.autocomplete
a été ajouté aux composants des champs nom d’utilisateur, courriel et mot de passe dans django.contrib.auth.forms
pour une meilleure interaction avec les gestionnaires de mots de passe des navigateurs.createsuperuser
se replie sur les variables d’environnement pour les champs mot de passe et autres champs obligatoires, lorsqu’elle ne trouve pas de paramètre correspondant sur la ligne de commande en mode non interactif.REQUIRED_FIELDS
prend dorénavant en charge les champs ManyToManyField
.UserManager.with_perm()
renvoie les utilisateurs ayant la permission indiquée.django.contrib.gis
¶GeometryDistance
a été ajoutée, prise en charge par PostGIS.furlong
(sillon) a été ajoutée dans Distance
.GEOIP_PATH
accepte maintenant les chemins pathlib.Path
.GeoIP2
accepte maintenant les chemins pathlib.Path
.django.contrib.postgres
¶RangeOperators
aide à éviter les erreurs de syntaxe dans les opérateurs SQL qui peuvent être utilisés conjointement avec RangeField
.RangeBoundary
représente les limites des intervalles.AddIndexConcurrently
et RemoveIndexConcurrently
permettent de créer et de supprimer des index de manière concurrente avec PostgreSQL.django.contrib.sessions
¶get_session_cookie_age()
permet de définir dynmaiquement l’âge du cookie de session.django.contrib.syndication
¶language
a été ajouté à django.contrib.syndication.views.Feed
pour pouvoir personnaliser la langue d’un flux. La valeur par défaut est get_language()
au lieu de LANGUAGE_CODE
.add_never_cache_headers()
et never_cache()
ajoutent dorénavant la directive private
aux en-têtes Cache-Control
.Storage.get_alternative_name()
permet d’adapter l’algorithme de génération des noms de fichiers lorsque le nom d’un fichier téléversé existe déjà.can_order
en définissant l’attribut ordering_widget
ou en surchargeant get_ordering_widget()
.LANGUAGE_COOKIE_HTTPONLY
, LANGUAGE_COOKIE_SAMESITE
et LANGUAGE_COOKIE_SECURE
ont été ajoutés pour définir les drapeaux HttpOnly
, SameSite
et Secure
sur les cookies de langue. Les valeurs par défaut de ces réglages préservent le comportement historique.reporter_class
de AdminEmailHandler
permet de fournir une sous-classe de django.views.debug.ExceptionReporter
pour personnaliser le texte de trace d’erreur envoyé aux ADMINS
du site lorsque DEBUG
vaut False
.compilemessages --ignore
permet d’ignorer des répertoires spécifiques lors de la recherche de fichiers .po
à compiler.showmigrations --list
affiche dorénavant la date d’application lorsque --verbosity
est de 2 ou plus.dbshell
prend dorénavant en charge les certificats TLS client.inspectdb
sait dorénavant découvrir les champs OneToOneField
lorsqu’une clé étrangère possède une contrainte unique ou de clé primaire.--skip-checks
omet l’exécution des contrôles système avant de lancer la commande.startapp --template
et startproject --template
prennent maintenant en charge les gabarits stockés dans des archives XZ (.tar.xz
, .txz
) et LZMA (.tar.lzma
, .tlz
).Les fonctions de base de données de génération d’empreintes MD5
, SHA1
, SHA224
, SHA256
, SHA384
et SHA512
ont été ajoutées.
La fonction de base de données Sign
a été ajoutée.
Le nouveau paramètre is_dst
des fonctions de base de données Trunc
détermine le traitement des heures non existantes ou ambiguës.
connection.queries
affiche dorénavant les instructions COPY … TO
avec PostgreSQL.
FilePathField
accepte dorénavant un objet exécutable pour path
.
Les tables intermédiaires symétriques sont permises pour les champs auto-référencés ManyToManyField
.
Les attributs name
de CheckConstraint
, UniqueConstraint
et Index
prennent dorénavant en charge l’interpolation de classe et d’étiquette d’application en utilisant les substituants '%(app_label)s'
et '%(class)s'
.
Le nouvel attribut Field.descriptor_class
permet aux champs de modèles de personnaliser le comportement get et set en surchargeant leurs descripteurs.
Le champ SmallAutoField
a été ajouté ; il est similaire à AutoField
sauf qu’il ne permet des valeurs que jusqu’à une certaine limite (dépendante de la base de données). Les valeurs de 1
à 32767
sont valables pour toutes les bases de données prises en charge par Django.
AutoField
, BigAutoField
et SmallAutoField
héritent dorénavant respectivement de IntegerField
, BigIntegerField
et SmallIntegerField
. Les contrôles système et les validateurs sont aussi correctement hérités.
FileField.upload_to
accepte maintenant les chemins pathlib.Path
.
CheckConstraint
est dorénavant prise en charge avec MySQL 8.0.16+.
La nouvelle méthode allows_group_by_selected_pks_on_model()
de django.db.backends.base.BaseDatabaseFeatures
permet d’optimiser les clauses GROUP BY
pour n’exiger que les clés primaires des modèles sélectionnés. Par défaut, elle n’est prise en charge que pour les modèles gérés avec PostgreSQL.
Pour activer l’optimisation de clé primaire seule pour GROUP BY
pour les modèles non gérés (« unmanaged »), vous deez créer une sous-classe du moteur de base de données PostgreSQL, surchargeant la classe de fonctionnalité features
avec une méthode allows_group_by_selected_pks_on_model()
selon vos besoins. Voir l’exemple Sous-classes des moteurs de base de données intégrés.
HttpResponse
peut maintenant être initialisée avec du contenu memoryview
.HttpRequest.headers
now
allows lookups using underscores (e.g. user_agent
) in place of hyphens.X_FRAME_OPTIONS
est dorénavant 'DENY'
. Dans les anciennes versions, cette valeur par défaut était 'SAMEORIGIN'
. Si votre site utilise des cadres (« frames ») de lui-même, vous devrez explicitement définir X_FRAME_OPTIONS = 'SAMEORIGIN'
pour qu’ils continuent à fonctionner.SECURE_CONTENT_TYPE_NOSNIFF
now defaults to True
. With this
enabled, SecurityMiddleware
sets the
X-Content-Type-Options: nosniff header on all responses that do not already
have it.SecurityMiddleware
peut dorénavant envoyer l’en-tête Referrer-Policy.raise_request_exception
de la classe de test Client
permet de contrôler si les exceptions générées pendant la requête doivent être propagées dans les tests. La valeur par défaut est True
pour des raisons de rétrocompatibilité. Quand elle vaut False
et qu’une exception survient, le client de test renverra une réponse 500 avec l’attribut exc_info
, un tuple fournissant des informations sur l’exception survenue.test -k
.assertHTMLEqual()
traite dorénavant le texte, les références de caractères et les références d’entité qui se réfèrent au même caractère comme équivalents.--headless
pour activer ce mode.--start-at
et --start-after
pour lancer les tests en commençant à partir d’un certain module de premier niveau.--pdb
pour déclencher un débogueur à chaque erreur ou échec.Model.save()
when providing a default for the primary key¶Model.save()
no longer attempts to find a row when saving a new
Model
instance and a default value for the primary key is provided, and
always performs a single INSERT
query. In older Django versions,
Model.save()
performed either an INSERT
or an UPDATE
based on
whether or not the row exists.
This makes calling Model.save()
while providing a default primary key value
equivalent to passing force_insert=True to
model’s save()
. Attempts to use a new Model
instance to update an
existing row will result in an IntegrityError
.
In order to update an existing model for a specific primary key value, use the
update_or_create()
method or
QuerySet.filter(pk=…).update(…)
instead. For example:
>>> MyModel.objects.update_or_create(pk=existing_pk, defaults={'name': 'new name'})
>>> MyModel.objects.filter(pk=existing_pk).update(name='new name')
Cette section décrit des modifications qui pourraient être nécessaires dans des moteurs de base de données tiers.
DatabaseIntrospection.get_geometry_type()
est dorénavant la description de la ligne au lieu du nom de la colonne.DatabaseIntrospection.get_field_type()
ne renvoie plus forcément des tuples.SchemaEditor.sql_create_column_inline_fk
à son moteur, avec le contenu SQL approprié ; sinon, définissez DatabaseFeatures.can_create_inline_fk = False
.DatabaseFeatures.can_return_id_from_insert
et can_return_ids_from_bulk_insert
sont renommés en can_return_columns_from_insert
et can_return_rows_from_bulk_insert
.datetime.timezone
lorsqu’elles sont créées avec des instances datetime.timedelta
(par ex. timezone(timedelta(hours=5))
, qui produirait 'UTC+05:00'
). Les moteurs tiers doivent prendre en compte ce format lors de la préparation de DateTimeField
dans datetime_cast_date_sql()
, datetime_extract_sql()
, etc.DatabaseOperations.integer_field_ranges
pour les champs AutoField
, BigAutoField
et SmallAutoField
afin de prendre en charge les validateurs d’intervalles de nombres entiers pour ces types de champ. Les moteurs tiers pourraient avoir à adapter les lignes par défaut.DatabaseOperations.fetch_returned_insert_id()
est remplacée par fetch_returned_insert_columns()
qui renvoie une liste de valeurs renvoyées par l’instruction INSERT … RETURNING
au lieu d’une valeur unique.DatabaseOperations.return_insert_id()
est remplacée par return_insert_columns()
qui accepte un paramètre fields
qui est un itérable de champs à renvoyer après l’insertion. Généralement, il ne s’agit que du champ clé primaire auto-généré.django.contrib.admin
¶django.contrib.gis
¶La prise en charge amont de PostgreSQL 9.4 se termine en décembre 2019. Django 3.0 prend en charge PostgreSQL 9.5 et plus récent.
La prise en charge de Oracle 12.1 par le projet amont se termine en juillet 2021. Django 2.2 sera pris en charge jusqu’en avril 2022. Django 3.0 prend officiellement en charge Oracle 12.2 et 18c.
Bien que la prise en charge de Python 2 ait été supprimée dans Django 2.0, certaines API privées n’ont pas été supprimées de Django afin que des applications tierces puissent continuer à les utiliser jusqu’à la fin de vie de Python 2.
Comme nous nous attendons à ce que les applications abandonnent la compatibilité avec Python 2 lors de l’ajout de la prise en charge de Django 3.0, nous supprimons ces API dans cette version.
django.test.utils.str_prefix()
- Les chaînes n’ont plus de préfixe « u » avec Python 3.django.test.utils.patch_logger()
- Utilisez unittest.TestCase.assertLogs()
à la place.django.utils.lru_cache.lru_cache()
- Alias de functools.lru_cache()
.django.utils.decorators.available_attrs()
- Cette fonction renvoie functools.WRAPPER_ASSIGNMENTS
.django.utils.decorators.ContextDecorator
- Alias de contextlib.ContextDecorator
.django.utils._os.abspathu()
- Alias de os.path.abspath()
.django.utils._os.upath()
et npath()
- Ces fonctions ne font plus rien en Python 3.django.utils.six
- Supprimez l’utilisation de cette bibliothèque embarquée ou passez à six.django.utils.encoding.python_2_unicode_compatible()
- Alias de six.python_2_unicode_compatible()
.django.utils.functional.curry()
- Utilisez functools.partial()
ou functools.partialmethod
. Voir 5b1c389603a353625ae1603.django.utils.safestring.SafeBytes
- Inutilisée depuis Django 2.0.FILE_UPLOAD_PERMISSIONS
¶Dans les versions précédentes, le réglage FILE_UPLOAD_PERMISSIONS
valait None
par défaut. Avec le gestionnaire par défaut FILE_UPLOAD_HANDLERS
, cela pouvait aboutir à des fichiers téléversés ayant des permissions différentes dépendant de leur taille et donc de quel gestionnaire de téléversement était utilisé.
FILE_UPLOAD_PERMISSION
contient désormais 0o644
par défaut pour éviter cette incohérence.
Pour rendre les projets Django plus sûrs par défaut, certains réglages de sécurité ont dorénavant des valeurs par défaut plus sûres :
X_FRAME_OPTIONS
est 'DENY'
.SECURE_CONTENT_TYPE_NOSNIFF
est True
.Consultez la section sécurité des nouveautés de Django 3.0 pour plus de détails sur ces changements.
ContentType.__str__()
inclut dorénavant l’étiquette app_label
de son modèle pour distinguer les modèles ayant le même nom dans des applications différentes.LocaleMiddleware
ne cherche plus la langue de l’utilisateur dans la session et django.contrib.auth.logout()
ne préserve plus la langue de la session après la déconnexion.django.utils.html.escape()
utilise dorénavant html.escape()
pour l’échappement du code HTML. Le guillemet simple '
est dorénavant converti en '
au lieu de l’équivalent en format décimal '
.django-admin test -k
fonctionne dorénavant comme l’option unittest -k
plutôt que comme un raccourci de --keepdb
.pywatchman
< 1.2.0 a été abandonnée.urlencode()
code dorénavant les valeurs itérables telles qu’elles sont lorsque doseq=False
, plutôt que de les passer en boucle, ce qui rapproche du comportement de la fonction de bibliothèque standard urllib.parse.urlencode()
.intword
traduit dorénavant 1.0
avec une phrase au singulier et toutes les autres valeurs numériques comme une phrase au pluriel, ce qui n’est pas toujours correct selon les langues.'_id'
d’un champ ForeignKey
ou OneToOneField
efface dorénavant la valeur du champ correspondant. Tout accès postérieur à ce champ aboutira à une nouvelle requête.patch_vary_headers()
traite dorénavant l’astérisque '*'
en accord avec la RFC 7231#section-7.1.4, c’est-à-dire que si une liste de noms de champs d’en-tête contient un astérisque, l’en-tête Vary
sera formé d’un seul astérisque '*'
.PositiveIntegerField
et PositiveSmallIntegerField
incluent dorénavant une contrainte de contrôle pour empêcher les valeurs négatives dans la base de données.alias=None
a été ajouté à la signature de Expression.get_group_by_cols()
.RegexPattern
, used by re_path()
, no longer returns
keyword arguments with None
values to be passed to the view for the
optional named groups that are missing.django.utils.encoding.force_text()
et smart_text()
¶Les alias smart_text()
et force_text()
(depuis Django 2.0) de smart_str()
et force_str()
sont rendus obsolètes. Vous pouvez ignorer l’avertissement si votre code prend en charge Python 2 car le comportement de smart_str()
et force_str()
est différent dans ce contexte.
django.utils.http.urlquote()
, urlquote_plus()
, urlunquote()
et urlunquote_plus()
sont rendus obsolètes en faveur des fonctions pour lesquelles elles sont des alias : urllib.parse.quote()
, quote_plus()
, unquote()
et unquote_plus()
.django.utils.translation.ugettext()
, ugettext_lazy()
, ugettext_noop()
, ungettext()
et ungettext_lazy()
sont rendues obsolètes en faveur des fonctions pour lesquelles elles sont des alias : django.utils.translation.gettext()
, gettext_lazy()
, gettext_noop()
, ngettext()
et ngettext_lazy()
.django.views.i18n.set_language()
arrêtera de définir la langue de l’utilisateur dans la session à partir de Django 4.0. Dès Django 2.1, la langue est toujours stockée dans le cookie LANGUAGE_COOKIE_NAME
.django.utils.text.unescape_entities()
est rendu obsolète en faveur de html.unescape()
. Notez qu’au contraire de unescape_entities()
, html.unescape()
évalue immédiatement les chaînes différées.is_safe_url()
a été renommé en url_has_allowed_host_and_scheme()
. Le fait que le protocole et l’hôte d’une URL soit autorisés n’implique en général pas qu’elle soit sûre. Elle pourrait par exemple être codée de façon incorrecte. Assurez-vous d’appliquer aussi iri_to_uri()
sur la partie chemin des URL de source non fiable.Ces fonctionnalités ont atteint la fin de leur cycle d’obsolescence et sont supprimées dans Django 3.0.
Voir Features deprecated in 2.0 pour les détails de ces changements, ainsi que pour savoir comment supprimer l’utilisation de ces fonctionnalités.
django.db.backends.postgresql_psycopg2
a été supprimé.django.shortcuts.render_to_response()
a été supprimée.DEFAULT_CONTENT_TYPE
a été supprimé.HttpRequest.xreadlines()
a été supprimée.context
de Field.from_db_value()
et de Expression.convert_value()
a été supprimée.field_name
de QuerySet.earliest()
et de latest()
a été supprimé.Voir Fonctionnalités rendues obsolètes dans Django 2.1 pour les détails de ces changements, ainsi que pour savoir comment supprimer l’utilisation de ces fonctionnalités.
ForceRHR
a été supprimée.django.utils.http.cookie_date()
a été supprimée.staticfiles
et admin_static
ont été supprimées.django.contrib.staticfiles.templatetags.staticfiles.static()
a été supprimée.août 03, 2020