Notes de publication de Django 3.0¶
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 de 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.
Compatibilité Python¶
Django 3.0 requiert Python 3.6, 3.7, 3.8 ou 3.9 (dès 3.0.11). 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.
Prise en charge des bibliothèques tierces pour les anciennes versions de Django¶
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.
Quoi de neuf dans Django 3.0¶
Prise en charge de MariaDB¶
Django prend dorénavant officiellement en charge MariaDB 10.1 ou plus récent. Lisez les notes MariaDB pour plus de détails.
Prise en charge d’ASGI¶
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.
Contraintes d’exclusion avec PostgreSQL¶
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.
Expressions de filtres¶
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.
Énumérations pour les choix de champs de modèles¶
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.
Fonctionnalités mineures¶
django.contrib.admin¶
La prise en charge de l’attribut
admin_order_fieldpour les propriétés dansModelAdmin.list_display.La nouvelle méthode
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.La bibliothèque Select2 a été mise à jour de la version 4.0.3 vers 4.0.7.
La version intégrée de jQuery a été mise à jour de 3.3.1 vers 3.4.1.
django.contrib.auth¶
Le nouvel attribut
reset_url_tokendansPasswordResetConfirmViewpermet de définir un paramètre jeton affiché comme composant des URL de réinitialisation de mot de passe.La classe
BaseBackenda été ajoutée pour faciliter la personnalisation des moteurs d’authentification.Added
get_user_permissions()method to mirror the existingget_group_permissions()method.L’attribut HTML
autocompletea été ajouté aux composants des champs nom d’utilisateur, courriel et mot de passe dansdjango.contrib.auth.formspour une meilleure interaction avec les gestionnaires de mots de passe des navigateurs.createsuperuserse 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_FIELDSprend dorénavant en charge les champsManyToManyField.La nouvelle méthode
UserManager.with_perm()renvoie les utilisateurs ayant la permission indiquée.Le nombre d’itération par défaut du hacheur de mot de passe PBKDF2 a été augmenté de 150’000 à 180’000.
django.contrib.gis¶
Les fonctions de requête spatiale MySQL opèrent dorénavant sur les géométries réelles. Précédemment, seules les boîtes englobantes étaient prises en compte.
La fonction
GeometryDistancea été ajoutée, prise en charge par PostGIS.La prise en charge de l’unité
furlong(sillon) a été ajoutée dansDistance.Le réglage
GEOIP_PATHaccepte maintenant les cheminspathlib.Path.La classe
GeoIP2accepte maintenant les cheminspathlib.Path.
django.contrib.postgres¶
La nouvelle classe
RangeOperatorsaide à éviter les erreurs de syntaxe dans les opérateurs SQL qui peuvent être utilisés conjointement avecRangeField.La nouvelle expression
RangeBoundaryreprésente les limites des intervalles.Les nouvelles classes
AddIndexConcurrentlyetRemoveIndexConcurrentlypermettent de créer et de supprimer des index de manière concurrente avec PostgreSQL.
django.contrib.sessions¶
The new
get_session_cookie_age()method allows dynamically specifying the session cookie age.
Cache¶
add_never_cache_headers()etnever_cache()ajoutent dorénavant la directiveprivateaux en-têtesCache-Control.
Stockage de fichier¶
La nouvelle méthode
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à.
Formulaires¶
Formsets may control the widget used when ordering forms via
can_orderby setting theordering_widgetattribute or overridingget_ordering_widget.
Internationalisation¶
Les réglages
LANGUAGE_COOKIE_HTTPONLY,LANGUAGE_COOKIE_SAMESITEetLANGUAGE_COOKIE_SECUREont été ajoutés pour définir les drapeauxHttpOnly,SameSiteetSecuresur les cookies de langue. Les valeurs par défaut de ces réglages préservent le comportement historique.La prise en charge des traductions en ouzbek a été ajoutée.
Journalisation¶
Le nouveau paramètre
reporter_classdeAdminEmailHandlerpermet de fournir une sous-classe dedjango.views.debug.ExceptionReporterpour personnaliser le texte de trace d’erreur envoyé auxADMINSdu site lorsqueDEBUGvautFalse.
Commandes d’administration¶
La nouvelle option
compilemessages --ignorepermet d’ignorer des répertoires spécifiques lors de la recherche de fichiers.poà compiler.showmigrations --listaffiche dorénavant la date d’application lorsque--verbosityest de 2 ou plus.Avec PostgreSQL,
dbshellprend dorénavant en charge les certificats TLS client.inspectdbsait dorénavant découvrir les champsOneToOneFieldlorsqu’une clé étrangère possède une contrainte unique ou de clé primaire.La nouvelle option
--skip-checksomet l’exécution des contrôles système avant de lancer la commande.Les options
startapp --templateetstartproject --templateprennent maintenant en charge les gabarits stockés dans des archives XZ (.tar.xz,.txz) et LZMA (.tar.lzma,.tlz).
Modèles¶
Les fonctions de base de données de génération d’empreintes
MD5,SHA1,SHA224,SHA256,SHA384etSHA512ont été ajoutées.La fonction de base de données
Signa été ajoutée.Le nouveau paramètre
is_dstdes fonctions de base de donnéesTruncdétermine le traitement des heures non existantes ou ambiguës.connection.queriesaffiche dorénavant les instructionsCOPY … TOavec PostgreSQL.FilePathFieldaccepte dorénavant un objet exécutable pourpath.Les tables intermédiaires symétriques sont permises pour les champs auto-référencés
ManyToManyField.Les attributs
namedeCheckConstraint,UniqueConstraintetIndexprennent dorénavant en charge l’interpolation de classe et d’étiquette d’application en utilisant les substituants'%(app_label)s'et'%(class)s'.The new
Field.descriptor_classattribute allows model fields to customize the get and set behavior by overriding their descriptors.Le champ
SmallAutoFielda été ajouté ; il est similaire àAutoFieldsauf qu’il ne permet des valeurs que jusqu’à une certaine limite (dépendante de la base de données). Les valeurs de1à32767sont valables pour toutes les bases de données prises en charge par Django.AutoField,BigAutoFieldetSmallAutoFieldhéritent dorénavant respectivement deIntegerField,BigIntegerFieldetSmallIntegerField. Les contrôles système et les validateurs sont aussi correctement hérités.FileField.upload_toaccepte maintenant les cheminspathlib.Path.CheckConstraintest dorénavant prise en charge avec MySQL 8.0.16+.La nouvelle méthode
allows_group_by_selected_pks_on_model()dedjango.db.backends.base.BaseDatabaseFeaturespermet d’optimiser les clausesGROUP BYpour 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 BYpour 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éfeaturesavec une méthodeallows_group_by_selected_pks_on_model()selon vos besoins. Voir l’exemple Sous-classes des moteurs de base de données intégrés.
Requêtes et réponses¶
HttpResponsepeut maintenant être initialisée avec du contenumemoryview.For use in, for example, Django templates,
HttpRequest.headersnow allows lookups using underscores (e.g.user_agent) in place of hyphens.
Sécurité¶
La valeur par défaut de
X_FRAME_OPTIONSest 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éfinirX_FRAME_OPTIONS = 'SAMEORIGIN'pour qu’ils continuent à fonctionner.SECURE_CONTENT_TYPE_NOSNIFFnow defaults toTrue. With this enabled,SecurityMiddlewaresets the X-Content-Type-Options: nosniff header on all responses that do not already have it.SecurityMiddlewarepeut dorénavant envoyer l’en-tête Referrer-Policy.
Tests¶
Le nouveau paramètre
raise_request_exceptionde la classe de testClientpermet 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 estTruepour des raisons de rétrocompatibilité. Quand elle vautFalseet qu’une exception survient, le client de test renverra une réponse 500 avec l’attributexc_info, un tuple fournissant des informations sur l’exception survenue.Les tests et les cas de tests à lancer peuvent être choisis par un motif de nom de test à l’aide de la nouvelle option
test -k.La comparaison HTML, telle qu’utilisée par
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.DiscoverRunnercan now spawn a debugger at each error or failure using thetest --pdboption.
Changements incompatibles avec les anciennes versions dans Django 3.0¶
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")
API de moteur de base de données¶
Cette section décrit des modifications qui pourraient être nécessaires dans des moteurs de base de données tiers.
Le second paramètre de
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.Si une base de données peut créer des clés étrangères dans la même instruction SQL qui ajoute un champ, ajoutez l’attribut
SchemaEditor.sql_create_column_inline_fkà son moteur, avec le contenu SQL approprié ; sinon, définissezDatabaseFeatures.can_create_inline_fk = False.DatabaseFeatures.can_return_id_from_insertetcan_return_ids_from_bulk_insertsont renommés encan_return_columns_from_insertetcan_return_rows_from_bulk_insert.Les fonctions de base de données prennent maintenant en charge les formats
datetime.timezonelorsqu’elles sont créées avec des instancesdatetime.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 deDateTimeFielddansdatetime_cast_date_sql(),datetime_extract_sql(), etc.Des lignes sont ajoutées à
DatabaseOperations.integer_field_rangespour les champsAutoField,BigAutoFieldetSmallAutoFieldafin 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 parfetch_returned_insert_columns()qui renvoie une liste de valeurs renvoyées par l’instructionINSERT … RETURNINGau lieu d’une valeur unique.DatabaseOperations.return_insert_id()est remplacée parreturn_insert_columns()qui accepte un paramètrefieldsqui 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¶
Les messages de changement des historiques de modèle du site d’administration préfèrent dorénavant les étiquettes de champ plus lisibles plutôt que les noms de champ.
django.contrib.gis¶
La prise en charge de PostGIS 2.1 a été supprimée.
La prise en charge de SpatiaLite 4.1 et 4.2 a été supprimée.
La prise en charge de GDAL 1.11 et GEOS 3.4 a été supprimée.
Abandon de la prise en charge de PostgreSQL 9.4¶
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.
Abandon de la prise en charge de Oracle 12.1¶
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.
Les API de compatibilité privées de Python 2 ont été supprimées.¶
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()- Utilisezunittest.TestCase.assertLogs()à la place.django.utils.lru_cache.lru_cache()- Alias defunctools.lru_cache().django.utils.decorators.available_attrs()- Cette fonction renvoiefunctools.WRAPPER_ASSIGNMENTS.django.utils.decorators.ContextDecorator- Alias decontextlib.ContextDecorator.django.utils._os.abspathu()- Alias deos.path.abspath().django.utils._os.upath()etnpath()- Ces fonctions ne font plus rien en Python 3.django.utils.six- Remove usage of this vendored library or switch to six.django.utils.encoding.python_2_unicode_compatible()- Alias desix.python_2_unicode_compatible().django.utils.functional.curry()- Usefunctools.partial()orfunctools.partialmethod. See 5b1c389603a353625ae1603ba345147356336afb.django.utils.safestring.SafeBytes- Inutilisée depuis Django 2.0.
Nouvelle valeur par défaut du réglage 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_PERMISSIONS now defaults to 0o644 to avoid this
inconsistency.
Nouvelles valeurs par défaut de réglages de sécurité¶
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 :
La nouvelle valeur par défaut de
X_FRAME_OPTIONSest'DENY'.La nouvelle valeur par défaut de
SECURE_CONTENT_TYPE_NOSNIFFestTrue.
Consultez la section sécurité des nouveautés de Django 3.0 pour plus de détails sur ces changements.
Divers¶
ContentType.__str__()inclut dorénavant l’étiquetteapp_labelde son modèle pour distinguer les modèles ayant le même nom dans des applications différentes.Comme l’accès à la langue dans la session a été rendu obsolète au profit des cookies,
LocaleMiddlewarene cherche plus la langue de l’utilisateur dans la session etdjango.contrib.auth.logout()ne préserve plus la langue de la session après la déconnexion.django.utils.html.escape()utilise dorénavanthtml.escape()pour l’échappement du code HTML. Le guillemet simple'est dorénavant converti en'au lieu de l’équivalent en format décimal'.L’option
django-admin test -kfonctionne dorénavant comme l’optionunittest -kplutôt que comme un raccourci de--keepdb.La prise en charge de
pywatchman< 1.2.0 a été abandonnée.urlencode()code dorénavant les valeurs itérables telles qu’elles sont lorsquedoseq=False, plutôt que de les passer en boucle, ce qui rapproche du comportement de la fonction de bibliothèque standardurllib.parse.urlencode().Le filtre de gabarit
intwordtraduit dorénavant1.0avec 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.Assigning a value to a model’s
ForeignKeyorOneToOneField'_id'attribute now unsets the corresponding field. Accessing the field afterward will result in a query.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êteVarysera formé d’un seul astérisque'*'.Avec MySQL 8.0.16+,
PositiveIntegerFieldetPositiveSmallIntegerFieldincluent dorénavant une contrainte de contrôle pour empêcher les valeurs négatives dans la base de données.alias=Nonea été ajouté à la signature deExpression.get_group_by_cols().RegexPattern, used byre_path(), no longer returns keyword arguments withNonevalues to be passed to the view for the optional named groups that are missing.
Fonctionnalités rendues obsolètes dans Django 3.0¶
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.
Divers¶
django.utils.http.urlquote(),urlquote_plus(),urlunquote()eturlunquote_plus()sont rendus obsolètes en faveur des fonctions pour lesquelles elles sont des alias :urllib.parse.quote(),quote_plus(),unquote()etunquote_plus().django.utils.translation.ugettext(),ugettext_lazy(),ugettext_noop(),ungettext()etungettext_lazy()sont rendues obsolètes en faveur des fonctions pour lesquelles elles sont des alias :django.utils.translation.gettext(),gettext_lazy(),gettext_noop(),ngettext()etngettext_lazy().Afin de limiter la création de sessions et donc de favorise certaines stratégies de cache,
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 cookieLANGUAGE_COOKIE_NAME.django.utils.text.unescape_entities()est rendu obsolète en faveur dehtml.unescape(). Notez qu’au contraire deunescape_entities(),html.unescape()évalue immédiatement les chaînes différées.Pour éviter une possible confusion sur sa portée réelle, l’utilitaire interne privé
is_safe_url()a été renommé enurl_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 aussiiri_to_uri()sur la partie chemin des URL de source non fiable.
Fonctionnalités supprimées dans 3.0¶
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.
Le module
django.db.backends.postgresql_psycopg2a été supprimé.django.shortcuts.render_to_response()a été supprimée.Le réglage
DEFAULT_CONTENT_TYPEa été supprimé.HttpRequest.xreadlines()a été supprimée.La prise en charge du paramètre
contextdeField.from_db_value()et deExpression.convert_value()a été supprimée.Le paramètre nommé
field_namedeQuerySet.earliest()et delatest()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.
La fonction SIG
ForceRHRa été supprimée.django.utils.http.cookie_date()a été supprimée.Les bibliothèques de balises de gabarits
staticfilesetadmin_staticont été supprimées.django.contrib.staticfiles.templatetags.staticfiles.static()a été supprimée.