Notes de publication de Django 5.1¶
7 août 2024
Bienvenue dans Django 5.1 !
Ces notes de publications couvrent les nouvelles fonctionnalités, ainsi que certaines modifications non rétrocompatibles dont il faut être au courant lors de la mise à jour depuis Django 5.0 ou des versions plus anciennes. 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 5.1 supports Python 3.10, 3.11, 3.12, and 3.13 (as of 5.1.3). We highly recommend and only officially support the latest release of each series.
Quoi de neuf dans Django 5.1¶
Balise de gabarit {% querystring %}¶
Django 5.1 introduit la balise de gabarit {% querystring %} pour simplifier la modification des paramètres de requête dans les URL, ce qui rend plus facile la génération de liens en conservant les paramètres de requête existants tout en en ajoutant ou en en modifiant certains.
Par exemple, la navigation dans la pagination et les paramètres de requête dans les gabarits peut se révéler compliquée. Imaginez ce fragment de gabarit qui génère dynamiquement une URL pour naviguer vers la page suivante dans le cadre d’une vue paginée :
{# Linebreaks added for readability, this should be one, long line. #}
<a href="?{% for key, values in request.GET.iterlists %}
{% if key != "page" %}
{% for value in values %}
{{ key }}={{ value }}&
{% endfor %}
{% endif %}
{% endfor %}page={{ page.next_page_number }}">Next page</a>
En utilisant la nouvelle balise de gabarit, le contenu ci-dessus devient magiquement :
<a href="{% querystring page=page.next_page_number %}">Next page</a>
Réserves de connexions PostgreSQL¶
Django 5.1 introduit aussi la prise en charge des réserves de connexion (pool) pour PostgreSQL. Comme le temps d’établissement d’une connexion peut être relativement lent, conserver des connexions ouvertes peut réduire la latence.
Pour utiliser une réserve de connexions avec psycopg, vous pouvez définir l’option "pool" dans OPTIONS, soit sous forme de dictionnaire à passer à ConnectionPool, soit avec la valeur True pour utiliser les valeurs par défaut de ConnectionPool:
DATABASES = {
"default": {
"ENGINE": "django.db.backends.postgresql",
# ...
"OPTIONS": {
"pool": {
"min_size": 2,
"max_size": 4,
"timeout": 10,
}
},
},
}
Intergiciel pour exiger l’authentification par défaut¶
Le nouvel intergiciel LoginRequiredMiddleware redirige toutes les requêtes non authentifiées ver une page de connexion. Les vues peuvent autoriser des requêtes non authentifiées en utilisant le nouveau décorateur login_not_required().
LoginRequiredMiddleware respecte les valeurs login_url et redirect_field_name définies via le décorateur login_required(), mais ne prend pas en charge la définition de login_url ou redirect_field_name via la classe LoginRequiredMixin.
Pour activer cette nouvelle fonctionnalité, ajoutez "django.contrib.auth.middleware.LoginRequiredMiddleware" à votre réglage MIDDLEWARE.
Fonctionnalités mineures¶
django.contrib.admin¶
ModelAdmin.list_displayaccepte désormais les accès avec__pour lister des champs de modèles liés.
django.contrib.auth¶
Le nombre d’itération par défaut du hacheur de mot de passe PBKDF2 a été augmenté de 720’000 à 870’000.
Le paramètre
parallelismpar défaut deScryptPasswordHashera été augmenté de 1 à 5, pour suivre les recommandations OWASP.Le nouveau formulaire
AdminUserCreationFormet le formulaire existantAdminPasswordChangeFormpermettent dorénavant de désactiver l’authentification par mot de passe en définissant un mot de passe inutilisable lors de l’enregistrement du formulaire. Cette fonctionnalité est accessible sur le site d’administration sur les pages de création d’utilisateur et de modification de mot de passe.Les décorateurs
login_required(),permission_required()etuser_passes_test()prennent maintenant en charge l’enveloppement de fonctions de vue asynchrones.ReadOnlyPasswordHashWidgetinclut dorénavant un bouton pour réinitialiser le mot de passe de l’utilisateur, qui remplace le lien précédemment imbriqué dans le texte d’aide deReadOnlyPasswordHashField, ce qui améliore l’accessibilité générale du formulaireUserChangeForm.
django.contrib.gis¶
BoundingCircleest dorénavant pris en charge avec SpatiaLite 5.1+.Collectest dorénavant prise en charge avec MySQL 8.0.24+.GeoIP2permet maintenant de faire des requêtes avec des objetsipaddress.IPv4Addressouipaddress.IPv6Address.GeoIP2.country()expose désormais les valeurscontinent_code,continent_nameetis_in_european_union.GeoIP2.city()expose désormais les valeursaccuracy_radiusetregion_name. De plus, les valeursdma_codeetregionsont désormais exposées sousmetro_codeetregion_code, mais les noms précédents sont aussi conservés par rétrocompatibilité.Areaprend désormais en charge l’unitéha(hectares).Le nouvel attribut
OGRGeometry.is_3dpermet de contrôler si une géométrie possède une coordonnée de dimensionZ.La nouvelle méthode
OGRGeometry.set_3d()permet l’ajout et la suppression de la coordonnée de dimensionZ.OGRGeometry,Point,LineString,PolygonetGeometryCollectionet leurs sous-classes prennent dorénavant en charge les géométries avec mesures via les nouvelles propriétésOGRGeometry.is_measuredetm, ainsi que la méthodeOGRGeometry.set_measured().OGRGeometry.centroidest maintenant disponible pour tous les types d’objets géométriques pris en charge.Les fonctions
FromWKB()etFromWKT()prennent désormais en charge l’argument facultatifsrid(sauf pour Oracle où cet argument est ignoré).
django.contrib.postgres¶
BTreeIndexprend désormais en charge le paramètrededuplicate_items.
django.contrib.sessions¶
django.contrib.sessions.backends.cached_db.SessionStoregère dorénavant les exceptions lors du stockage des informations de session dans le cache, journalisant les messages d’erreur appropriés avec leur trace d’erreur dans le journaliseur de sessions nouvellement ajouté.django.contrib.sessions.backends.base.SessionBaseet tous les moteurs de sessions intégrés fournissent une API asynchrones. Les nouvelles méthodes asynchrones ont toutes un préfixea, par ex.aget(),akeys()ouacycle_key().
Moteurs de base de données¶
L’option
"init_command"est dorénavant prise en charge dans lesOPTIONSde SQLite pour permettre d’indiquer des options pragma à définir à l’établissement des connexions.L’option
"transaction_mode"est dorénavant prise en charge dans lesOPTIONSde SQLite pour permettre d’indiquer le Comportement des transactions.L’option
"pool"est dorénavant prise en charge dans lesOPTIONSde PostgreSQL pour permettre d’utiliser les réserves de connexions.
Signalement d’erreurs¶
Afin d’améliorer l’accessibilité, les pages d’erreur 404 et 500 utilisent dorénavant les éléments de positionnement HTML pour l’en-tête, le pied de page et les principales zones de contenus.
Stockage de fichier¶
Le paramètre
allow_overwritedeFileSystemStoragepermet maintenant d’enregistrer des nouveaux fichiers en écrasant les anciens de même nom.
Formulaires¶
Dans l’optique d’améliorer l’accessibilité et de permettre aux lecteurs d’écran d’associer les groupes de champs avec leur texte d’aide, les groupes de champs de formulaires incluent dorénavant l’attribut HTML
aria-describedby.
Commandes d’administration¶
La commande
makemigrationsaffiche dorénavant des symboles significatifs pour chaque opération afin de mettre en évidence lescatégories d'opérations.
Migrations¶
Le nouvel attribut
Operation.categorypermet d’indiquer unecatégorie d'opérationutilisée par la commandemakemigrationspour afficher un symbole significatif de l’opération.
Modèles¶
QuerySet.explain()prend en charge dorénavant l’optiongeneric_plande PostgreSQL 16+.RowRangeaccepte dorénavant des entiers positifs pour l’argumentstartet des entiers négatifs pour l’argumentend.Le nouvel argument
exclusiondeRowRangeetValueRangepermet d’exclure des lignes, des groupes et des « ties » des cadres de fenêtres.QuerySet.order_by()prend dorénavant en charge le tri par annotations de transformation telles que des clésJSONObjectet des indicesArrayAgg.Les expressions
F()etOuterRef()qui résultent en champsCharField,EmailField,SlugField,URLField,TextFieldouArrayFieldpeuvent dorénavant être segmentées.Le nouvel argument
from_querysetdeModel.refresh_from_db()etModel.arefresh_from_db()permet de personnaliser le jeu de requête utilisé pour recharger les valeurs d’un modèle. Cela peut être utilisé pour verrouiller une ligne avant le rechargement ou pour précharger des objets liés.Le nouvel attribut
Expression.constraint_validation_compatiblepermet d’indiquer que l’expression doit être ignorée lors de la validation de contrainte.
Gabarits¶
Des balises personnalisées peuvent maintenant définir des données supplémentaires sur l’objet
Parserqui seront ensuite disponibles sur l’instanceTemplate. De telles données peuvent par exemple être utilisées par le chargeur de gabarits, ou d’autres clients des gabarits.Les moteurs de gabarits implémentent dorénavant une méthode
check()qui est déjà inscrite dans l’infrastructure des contrôles.
Tests¶
Les assertions
assertContains(),assertNotContains()etassertInHTML()ajoutent maintenant les contenus recherchés aux messages d’erreur des assertions.Les classes
RequestFactory,AsyncRequestFactory,ClientetAsyncClientprennent désormais en charge le paramètrequery_paramsqui accepte un dictionnaire de clés/valeurs de chaînes de requête. Cela permet de définir plus facilement des chaînes de requête pour toute méthode HTTP.self.client.post("/items/1", query_params={"action": "delete"}) await self.async_client.post("/items/1", query_params={"action": "delete"})
La nouvelle assertion
SimpleTestCase.assertNotInHTML()permet de tester qu’un fragment HTML n’est pas contenu dans le contenu de recherche HTML donné.Dans le but de renforcer l’isolation des tests, les connexions de base de données à l’intérieur des fils d’exécution ne sont plus autorisées dans
SimpleTestCase.
Validateurs¶
Le nouveau validateur
DomainNameValidatorvalide les noms de domaine, y compris les noms de domaine internationalisés. La nouvelle fonctionvalidate_domain_name()renvoie une instance deDomainNameValidator.
Changements incompatibles avec les anciennes versions dans Django 5.1¶
django.contrib.gis¶
La prise en charge de PostGIS 2.5 a été supprimée.
La prise en charge de PROJ < 6 a été supprimée.
La prise en charge de GDAL 2.4 a été supprimée.
GeoIP2n’ouvre plus à la fois les bases de donnéescityetcountrylorsque un chemin vers un répertoire est indiqué, préférant la base de donnéescityquand elle est disponible. La base de données des pays est un sous-ensemble de la base de données des villes et il n’y a souvent pas besoin des deux. Si vous avez vraiment besoin de la base de données des pays se trouvant dans le même répertoire de celle des villes, passez explicitement le chemin vers la base de données des pays dans le constructeur.
Abandon de la prise en charge de MariaDB 10.4¶
La prise en charge amont de MariaDB 10.4 se termine en juin 2024. Django 5.1 prend en charge MariaDB 10.5 et plus récent.
Abandon de la prise en charge de PostgreSQL 12¶
La prise en charge amont de PostgreSQL 12 se termine en novembre 2024. Django 5.1 prend en charge PostgreSQL 13 et plus récent.
Divers¶
Afin d’améliorer l’accessibilité, le filtre de la liste pour modification du site d’administration est produit dans une balise
<nav>au lieu d’une<div>.Afin d’améliorer l’accessibilité, le pied de page du site d’administration est produit dans une balise
<footer>au lieu d’une<div>, et il a aussi été déplacé au-dessous de l’élément<div id="main">.Afin d’améliorer l’accessibilité, le composant d’extension utilisé pour les groupes de champs
ModelAdmin.fieldsetsetInlineModelAdmin.fieldsetsquand le groupe est nommé et utilise la classecollapse, contient désormais les balises<details>et<summary>.Le fichier JavaScript
collapse.jsa été supprimé car il n’est plus nécessaire au site d’administration de Django.SimpleTestCase.assertURLEqual()etassertInHTML()ajoutent maintenant": "àmsg_prefix, par cohérence avec le comportement des autres assertions.django.utils.text.Truncatorused bytruncatechars_htmlandtruncatewords_htmltemplate filters now useshtml.parser.HTMLParsersubclasses. This results in a more robust and faster operation, but there may be small differences in the output.La fonction non documentée
django.urls.converters.get_converter()est supprimée.La version minimum de SQLite prise en charge est passée de 3.27.0 à 3.31.0.
FileFieldgénère dorénavant une exceptionFieldErrorlors de l’enregistrement d’un fichier sans nomname.ImageField.update_dimension_fields(force=True)n’est plus appelée après l’enregistrement de l’image dans le stockage. Si votre moteur de stockage redimensionne les images, les champswidth_fieldetheight_fieldne correspondront pas à la largeur et la hauteur de l’image.La version minimum de
asgirefprise en charge est passée de 3.7.0 à 3.8.1.To improve performance, the
delete_selectedadmin action now usesQuerySet.bulk_create()when creating multipleLogEntryobjects. As a result,pre_saveandpost_savesignals forLogEntryare not sent when multiple objects are deleted via this admin action.
Fonctionnalités rendues obsolètes dans Django 5.1¶
Divers¶
Les méthodes
ModelAdmin.log_deletion()etLogEntryManager.log_action()sont obsolètes. Ce sont les sous-classes qui doivent implémenter ces deux méthodes.La fonction non documentée
django.utils.itercompat.is_iterable()et le moduledjango.utils.itercompatsont obsolètes. Utilisez isinstance(…, collections.abc.Iterable)` à la place.La méthode
django.contrib.gis.geoip2.GeoIP2.coords()est obsolète. Utilisezdjango.contrib.gis.geoip2.GeoIP2.lon_lat()à la place.La méthode
django.contrib.gis.geoip2.GeoIP2.open()est obsolète. Utilisez le constructeurGeoIP2à la place.La transmission d’arguments positionnels à
Model.save()etModel.asave()a été rendue obsolète en faveur des arguments nommés.L’accès en écriture à
django.contrib.gis.gdal.OGRGeometry.coord_dimest obsolète. Utilisezset_3d()à la place.La surcharge de convertisseurs existants avec
django.urls.register_converter()est obsolète.Le paramètre nommé
checkdeCheckConstraintest obsolète, ce paramètre doit s’appeler dorénavantcondition.La propriété non documentée
OS_OPEN_FLAGSdeFileSystemStorageest obsolète. Pour permettre l’écrasement de fichiers dans un stockage, définissez la nouvelle optionallow_overwriteàTrue.La méthode
get_cache_name()deFieldCacheMixinest obsolète en faveur de la propriété en cachecache_name.
Fonctionnalités supprimées dans 5.1¶
Ces fonctionnalités ont atteint la fin de leur cycle d’obsolescence et sont supprimées dans Django 5.1.
Voir Fonctionnalités rendues obsolètes dans Django 4.2 pour les détails de ces changements, ainsi que pour savoir comment supprimer l’utilisation de ces fonctionnalités.
La méthode
BaseUserManager.make_random_password()est supprimée.L’option de modèle
Meta.index_togetherest supprimée.Le filtre de gabarit
length_isest supprimé.Les classes
django.contrib.auth.hashers.SHA1PasswordHasher,django.contrib.auth.hashers.UnsaltedSHA1PasswordHasheretdjango.contrib.auth.hashers.UnsaltedMD5PasswordHashersont supprimées.Les modèles
django.contrib.postgres.fields.CICharField,django.contrib.postgres.fields.CIEmailFieldetdjango.contrib.postgres.fields.CITextFieldsont supprimés, sauf pour leur prise en charge dans les migrations historiques.La classe mixin
django.contrib.postgres.fields.CITextest supprimée.Les attributs
map_widthetmap_heightdeBaseGeometryWidgetsont supprimés.La méthode
SimpleTestCase.assertFormsetError()est supprimée.La méthode
TransactionTestCase.assertQuerysetEqual()est supprimée.La prise en charge des chaînes littérales encodées en JSON à
JSONFieldet aux requêtes et expressions associées est supprimée.La prise en charge des arguments positionnels à
SigneretTimestampSignerest supprimée.Les réglages
DEFAULT_FILE_STORAGEetSTATICFILES_STORAGEsont supprimés.La fonction
django.core.files.storage.get_storage_class()est supprimée.