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.
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.
{% 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>
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,
}
},
},
}
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
.
django.contrib.admin
¶ModelAdmin.list_display
accepte 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 parallelism
par défaut de ScryptPasswordHasher
a été augmenté de 1 à 5, pour suivre les recommandations OWASP.
Le nouveau formulaire AdminUserCreationForm
et le formulaire existant AdminPasswordChangeForm
permettent 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()
et user_passes_test()
prennent maintenant en charge l’enveloppement de fonctions de vue asynchrones.
ReadOnlyPasswordHashWidget
inclut 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 de ReadOnlyPasswordHashField
, ce qui améliore l’accessibilité générale du formulaire UserChangeForm
.
django.contrib.gis
¶BoundingCircle
est dorénavant pris en charge avec SpatiaLite 5.1+.
Collect
est dorénavant prise en charge avec MySQL 8.0.24+.
GeoIP2
permet maintenant de faire des requêtes avec des objets ipaddress.IPv4Address
ou ipaddress.IPv6Address
.
GeoIP2.country()
expose désormais les valeurs continent_code
, continent_name
et is_in_european_union
.
GeoIP2.city()
expose désormais les valeurs accuracy_radius
et region_name
. De plus, les valeurs dma_code
et region
sont désormais exposées sous metro_code
et region_code
, mais les noms précédents sont aussi conservés par rétrocompatibilité.
Area
prend désormais en charge l’unité ha
(hectares).
Le nouvel attribut OGRGeometry.is_3d
permet de contrôler si une géométrie possède une coordonnée de dimension Z
.
La nouvelle méthode OGRGeometry.set_3d()
permet l’ajout et la suppression de la coordonnée de dimension Z
.
OGRGeometry
, Point
, LineString
, Polygon
et GeometryCollection
et leurs sous-classes prennent dorénavant en charge les géométries avec mesures via les nouvelles propriétés OGRGeometry.is_measured
et m
, ainsi que la méthode OGRGeometry.set_measured()
.
OGRGeometry.centroid
est maintenant disponible pour tous les types d’objets géométriques pris en charge.
Les fonctions FromWKB()
et FromWKT()
prennent désormais en charge l’argument facultatif srid
(sauf pour Oracle où cet argument est ignoré).
django.contrib.postgres
¶BTreeIndex
prend désormais en charge le paramètre deduplicate_items
.
django.contrib.sessions
¶django.contrib.sessions.backends.cached_db.SessionStore
gè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.SessionBase
et tous les moteurs de sessions intégrés fournissent une API asynchrones. Les nouvelles méthodes asynchrones ont toutes un préfixe a
, par ex. aget()
, akeys()
ou acycle_key()
.
L’option "init_command"
est dorénavant prise en charge dans les OPTIONS
de 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 les OPTIONS
de SQLite pour permettre d’indiquer le Comportement des transactions.
L’option "pool"
est dorénavant prise en charge dans les OPTIONS
de PostgreSQL pour permettre d’utiliser les réserves de connexions.
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.
Le paramètre allow_overwrite
de FileSystemStorage
permet maintenant d’enregistrer des nouveaux fichiers en écrasant les anciens de même nom.
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
.
La commande makemigrations
affiche dorénavant des symboles significatifs pour chaque opération afin de mettre en évidence les catégories d'opérations
.
Le nouvel attribut Operation.category
permet d’indiquer une catégorie d'opération
utilisée par la commande makemigrations
pour afficher un symbole significatif de l’opération.
QuerySet.explain()
prend en charge dorénavant l’option generic_plan
de PostgreSQL 16+.
RowRange
accepte dorénavant des entiers positifs pour l’argument start
et des entiers négatifs pour l’argument end
.
Le nouvel argument exclusion
de RowRange
et ValueRange
permet 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és JSONObject
et des indices ArrayAgg
.
Les expressions F()
et OuterRef()
qui résultent en champs CharField
, EmailField
, SlugField
, URLField
, TextField
ou ArrayField
peuvent dorénavant être segmentées.
Le nouvel argument from_queryset
de Model.refresh_from_db()
et Model.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_compatible
permet d’indiquer que l’expression doit être ignorée lors de la validation de contrainte.
Des balises personnalisées peuvent maintenant définir des données supplémentaires sur l’objet Parser
qui seront ensuite disponibles sur l’instance Template
. 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.
Les assertions assertContains()
, assertNotContains()
et assertInHTML()
ajoutent maintenant les contenus recherchés aux messages d’erreur des assertions.
Les classes RequestFactory
, AsyncRequestFactory
, Client
et AsyncClient
prennent désormais en charge le paramètre query_params
qui 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
.
Le nouveau validateur DomainNameValidator
valide les noms de domaine, y compris les noms de domaine internationalisés. La nouvelle fonction validate_domain_name()
renvoie une instance de DomainNameValidator
.
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.
GeoIP2
n’ouvre plus à la fois les bases de données city
et country
lorsque un chemin vers un répertoire est indiqué, préférant la base de données city
quand 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.
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.
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.
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.fieldsets
et InlineModelAdmin.fieldsets
quand le groupe est nommé et utilise la classe collapse
, contient désormais les balises <details>
et <summary>
.
Le fichier JavaScript collapse.js
a été supprimé car il n’est plus nécessaire au site d’administration de Django.
SimpleTestCase.assertURLEqual()
et assertInHTML()
ajoutent maintenant ": "
à msg_prefix
, par cohérence avec le comportement des autres assertions.
django.utils.text.Truncator
utilisé par les filtres de gabarit truncatechars_html
et truncatewords_html
utilisent dorénavant des sous-classes de html.parser.HTMLParser
. Le résultat en est plus robuste et rapide, mais il se peut qu’il y ait de petites différences dans le résultat obtenu.
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.
FileField
génère dorénavant une exception FieldError
lors de l’enregistrement d’un fichier sans nom name
.
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 champs width_field
et height_field
ne correspondront pas à la largeur et la hauteur de l’image.
La version minimum de asgiref
prise en charge est passée de 3.7.0 à 3.8.1.
To improve performance, the delete_selected
admin action now uses
QuerySet.bulk_create()
when creating multiple LogEntry
objects. As a
result, pre_save
and post_save
signals for LogEntry
are not sent
when multiple objects are deleted via this admin action.
Les méthodes ModelAdmin.log_deletion()
et LogEntryManager.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 module django.utils.itercompat
sont obsolètes. Utilisez isinstance(…, collections.abc.Iterable)` à la place.
La méthode django.contrib.gis.geoip2.GeoIP2.coords()
est obsolète. Utilisez django.contrib.gis.geoip2.GeoIP2.lon_lat()
à la place.
La méthode django.contrib.gis.geoip2.GeoIP2.open()
est obsolète. Utilisez le constructeur GeoIP2
à la place.
La transmission d’arguments positionnels à Model.save()
et Model.asave()
a été rendue obsolète en faveur des arguments nommés.
L’accès en écriture à django.contrib.gis.gdal.OGRGeometry.coord_dim
est obsolète. Utilisez set_3d()
à la place.
La surcharge de convertisseurs existants avec django.urls.register_converter()
est obsolète.
Le paramètre nommé check
de CheckConstraint
est obsolète, ce paramètre doit s’appeler dorénavant condition
.
La propriété non documentée OS_OPEN_FLAGS
de FileSystemStorage
est obsolète. Pour permettre l’écrasement de fichiers dans un stockage, définissez la nouvelle option allow_overwrite
à True
.
La méthode get_cache_name()
de FieldCacheMixin
est obsolète en faveur de la propriété en cache cache_name
.
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_together
est supprimée.
Le filtre de gabarit length_is
est supprimé.
Les classes django.contrib.auth.hashers.SHA1PasswordHasher
, django.contrib.auth.hashers.UnsaltedSHA1PasswordHasher
et django.contrib.auth.hashers.UnsaltedMD5PasswordHasher
sont supprimées.
Les modèles django.contrib.postgres.fields.CICharField
, django.contrib.postgres.fields.CIEmailField
et django.contrib.postgres.fields.CITextField
sont supprimés, sauf pour leur prise en charge dans les migrations historiques.
La classe mixin django.contrib.postgres.fields.CIText
est supprimée.
Les attributs map_width
et map_height
de BaseGeometryWidget
sont 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 à JSONField
et aux requêtes et expressions associées est supprimée.
La prise en charge des arguments positionnels à Signer
et TimestampSigner
est supprimée.
Les réglages DEFAULT_FILE_STORAGE
et STATICFILES_STORAGE
sont supprimés.
La fonction django.core.files.storage.get_storage_class()
est supprimée.
avr. 05, 2025