# Documentation Django 5.2.8

# 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 }}&amp;
        {% 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_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()`.

#### Moteurs de base de données

- 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.

#### 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_overwrite` de `FileSystemStorage` permet 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 `makemigrations` affiche dorénavant des symboles significatifs pour chaque opération afin de mettre en évidence les `catégories d'opérations`.

#### Migrations

- 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.

#### Modèles

- `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.

#### Gabarits

- 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.

#### Tests

- 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`.

#### Validateurs

- 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`.

## 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.

- `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.

### 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.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` used by `truncatechars_html` and `truncatewords_html` template filters now uses `html.parser.HTMLParser` subclasses. 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.

- `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.

## Fonctionnalités rendues obsolètes dans Django 5.1

### Divers

- 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`.

## 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_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.