# Documentation Django 3.1.9.dev

# Notes de publication de Django 2.2

1er avril 2019

Bienvenue dans Django 2.2 !

Ces notes de publications couvrent les nouvelles fonctionnalités, ainsi que certaines modifications non rétrocompatibles dont il faut être au courant lors la mise à jour depuis Django 2.1 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 2.2 is designated as a long-term support release. It will receive security updates for at least three years after its release. Support for the previous LTS, Django 1.11, will end in April 2020.

## Compatibilité Python

Django 2.2 supports Python 3.5, 3.6, 3.7, 3.8 (as of 2.2.8), and 3.9 (as of 2.2.17). We highly recommend and only officially support the latest release of each series.

## Quoi de neuf dans Django 2.2

### Contraintes

Les nouvelles classes class:~django.db.models.CheckConstraint and `UniqueConstraint` permettent d’ajouter des contraintes de base de données personnalisées. Ces contraintes peuvent être ajoutées aux modèles en utilisant l’option `Meta.constraints`.

### Fonctionnalités mineures

#### `django.contrib.admin`

- Une classe CSS a été ajoutée aux en-têtes de colonnes de `TabularInline`.

#### `django.contrib.auth`

- La requête `HttpRequest` est dorénavant transmise comme premier paramètre positionnel à `RemoteUserBackend.configure_user()`, si celle-ci l’accepte.

#### `django.contrib.gis`

- La prise en charge de la fonction `Envelope` a été ajoutée pour Oracle.
- La prise en charge des expressions de recherche `coveredby` and `covers` a été ajoutée pour SpatiaLite.

#### `django.contrib.postgres`

- Le nouveau paramètre `ordering` de `ArrayAgg` et `StringAgg` détermine l’ordre des éléments agrégés.
- Les nouvelles classes `BTreeIndex`, `HashIndex` et `SpGistIndex` permettent de créer des index `B-Tree`, `hash` et `SP-GiST` dans la base de données.
- `BrinIndex` possède maintenant le paramètre `autosummarize`.
- Le nouveau paramètre `search_type` de `SearchQuery` permet de rechercher une phrase ou une expression brute.

#### `django.contrib.staticfiles`

- La correspondance de chemins a été ajoutée à l’option `collectstatic --ignore` afin de pouvoir utiliser des motifs du genre `/vendor/*.js`.

#### Moteurs de base de données

- Avec SQLite, la diffusion en flux des résultats a été ajoutée pour `QuerySet.iterator()`.

#### Vues génériques

- Le nouveau point d’entrée `View.setup` initialise les attributs des vues avant d’appeler `dispatch()`. Cela permet aux classes mixin de configurer les attributs d’instance pour une réutilisation dans les classes enfants.

#### Internationalisation

- La prise en charge des traductions en arménien a été ajoutée.

#### Commandes d’administration

- La nouvelle option option:–force-color force la coloration des résultats de commandes.
- `inspectdb` crée dorénavant des modèles pour les tables étrangères avec PostgreSQL.
- `inspectdb --include-views` crée dorénavant des modèles pour les vues matérialisées avec Oracle et PostgreSQL.
- La nouvelle option `inspectdb --include-partitions` permet de créer des modèles pour les tables de partitions avec PostgreSQL. Dans les versions précédentes, les modèles étaient créés comme tables enfants au lieu de parents.
- `inspectdb` sait dorénavant découvrir les champs `DurationField` avec Oracle et PostgreSQL, ainsi que les champs `AutoField` avec SQLite.
- Avec Oracle, `dbshell` est envelopéé dans `rlwrap`, si disponible. `rlwrap` fournit un historique des commandes et permet d’éditer les saisies au clavier.
- La nouvelle option `makemigrations --no-header` permet d’éviter les commentaires en en-tête dans les fichiers de migration générés. Cette option est aussi disponible pour `squashmigrations`.
- `runserver` peut dorénavant exploiter Watchman pour améliorer les performances lors de la surveillance de modification pour de nombreux fichiers.

#### Migrations

- La nouvelle option `migrate --plan` imprime la liste des opérations de migration qui seront effectuées.
- `NoneType` peut maintenant être sérialisé dans les migrations.
- Il est maintenant possible d”inscrire des sérialiseurs personnalisés pour les migrations.

#### Modèles

- La prise en charge des opérateurs de classes PostgreSQL (`Index.opclasses`) a été ajoutée.
- La prise en charge des index partiels (`Index.condition`) a été ajoutée.
- Les fonctions de base de données class:~django.db.models.functions.NullIf et `Reverse` ont été ajoutées, de même que de nombreuses fonctions de base de données mathématiques.
- La définition du nouveau paramètre `ignore_conflicts` de `QuerySet.bulk_create()` à `True` indique à la base de données d’ignorer les insertions de lignes qui ne passent pas les contrôles d’unicité et autres contrôles.
- La nouvelle fonction `ExtractIsoYear` extrait les années avec numéro de semaine ISO-8601 des champs `DateField` et `DateTimeField`, et la nouvelle expression de requête `iso_year` permet d’interroger selon une année avec numéro de semaine ISO-8601.
- La nouvelle méthode `QuerySet.bulk_update()` permet de mettre à jour efficacement des champs spécifiques sur plusieurs instances de modèles.
- Django ne démarre plus automatiquement une transaction lors de l’exécution d’une seule requête, telle que `Model.save()`, `QuerySet.update()` et `Model.delete()`. Cela améliore la performance en mode commit automatique en diminuant le nombre d’aller-retour vers la base de données.
- La prise en charge des fonctions `StdDev` et `Variance` a été ajoutée pour SQLite.
- La gestion des agrégats avec `DISTINCT` a été ajoutée à la classe `Aggregate`. La définition de `allow_distinct = True` comme attribut de classe sur des sous-classes de `Aggregate` permet d’indiquer un paramètre nommé `distinct` lors de l’initialisation pour s’assurer que la fonction d’agrégat n’est appelée que pour chaque valeur distincte de `expressions`.
- Les méthodes `RelatedManager.add()`, `create()`, `remove()`, `set()`, `get_or_create()` et `update_or_create()` sont dorénavant autorisées sur des relations plusieurs-à-plusieurs avec modèle intermédiaire. Le nouveau paramètre `through_defaults` est utilisé pour indiquer des valeurs à définir sur la ou les instances de modèle intermédiaire.

#### Requêtes et réponses

- L’attribut `HttpRequest.headers` a été ajouté pour permettre un accès simplifié aux en-têtes de requêtes.

#### Sérialisation

- Il est dorénavant possible de désérialiser des données en utilisant des clés naturelles contenant des références en aval en passant `handle_forward_references=True` à `serializers.deserialize()`. De plus, `loaddata` gère automatiquement les références en aval.

#### Tests

- La nouvelle assertion `SimpleTestCase.assertURLEqual()` vérifie l’égalité avec une URL donnée en ignorant l’ordre des paramètres de la chaîne de requête. `assertRedirects()` utilise cette nouvelle assertion.
- Le client de test `Client` prend dorénavant en charge automatiquement la sérialisation JSON des listes et tuples `data` lorsque `content_type='application/json'`.
- Le nouveau réglage de base de données de test `ORACLE_MANAGED_FILES` permet d’utiliser des espaces de tables Oracle Managed Files (OMF).
- Les contraintes de base de données différables sont dorénavant appliquées à la fin de chaque test `TestCase` avec SQLite 3.20+, tout comme c’est déjà le cas pour les autres moteurs qui prennent en charge ce type de contraintes. Ces contrôles ne sont pas appliqués pour les versions plus anciennes de SQLite car ils nécessiteraient de coûteuses introspections de tables.
- `DiscoverRunner` ne configure plus les bases de données qui ne sont pas référencées par les tests.

#### URL

- Le nouvel attribut `ResolverMatch.route` stocke la route du motif d’URL correspondant.

#### Validateurs

- `MaxValueValidator`, `MinValueValidator`, `MinLengthValidator` et `MaxLengthValidator` acceptent maintenant une valeur `limit_value` exécutable.

## Changements incompatibles avec les anciennes versions dans Django 2.2

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

- Les moteurs de base de données de tierce-partie doivent implémenter la prise en charge des contraintes de vérification sur les tables ou définir `DatabaseFeatures.supports_table_check_constraints` à `False`.
- Les moteurs de base de données de tierce-partie doivent implémenter la capacité d’ignorer les contraintes ou erreurs d’unicité lors d’insertions, ou définir `DatabaseFeatures.supports_ignore_conflicts` à `False`.
- Les moteurs de base de données de tierce-partie doivent implémenter l’introspection pour `DurationField` ou définir `DatabaseFeatures.can_introspect_duration_field` à `False`.
- `DatabaseFeatures.uses_savepoints` vaut dorénavant `True` par défaut.
- Les moteurs de base de données de tierce-partie doivent implémenter la prise en charge des index partiels ou définir `DatabaseFeatures.supports_partial_indexes` à `False`.
- `DatabaseIntrospection.table_name_converter()` et `column_name_converter()` ont été supprimées. Les moteurs de base de données de tierce-partie peuvent devoir implémenter `DatabaseIntrospection.identifier_converter()` à la place. Dans ce cas, les noms de contraintes renvoyés par `DatabaseIntrospection.get_constraints()` doivent être normalisés par `identifier_converter()`.
- La génération SQL des index a été déplacée de `Index` vers `SchemaEditor` et ces méthodes de `SchemaEditor` ont été ajoutées :
  - `_create_primary_key_sql()` et `_delete_primary_key_sql()`
  - `_delete_index_sql()` (en réponse à `_create_index_sql()`)
  - `_delete_unique_sql` (en réponse à `_create_unique_sql()`)
  - `_delete_fk_sql()` (en réponse à `_create_fk_sql()`)
  - `_create_check_sql()` et `_delete_check_sql()`
- Le troisième paramètre de `DatabaseWrapper.__init__()`, `allow_thread_sharing`, a été supprimé.

### Les actions d’administration ne sont plus collectées à partir des classes `ModelAdmin` de base

Par exemple, dans les anciennes versions de Django

    from django.contrib import admin

    class BaseAdmin(admin.ModelAdmin):
        actions = ['a']

    class SubAdmin(BaseAdmin):
        actions = ['b']

`SubAdmin` disposait des actions `'a'` et `'b'`.

Dorénavant les `actions` suivent l’héritage Python standard. Pour obtenir le même résultat qu’auparavant

    class SubAdmin(BaseAdmin):
        actions = BaseAdmin.actions + ['b']

### `django.contrib.gis`

- La prise en charge de GDAL 1.9 et 1.10 a été abandonnée.

### Chargement de données `TransactionTestCase` sérialisées

Les migrations de données initiales sont dorénavant chargées dans `TransactionTestCase` à la fin du test, après la réinitialisation de la base de données. Dans les anciennes versions, ces données étaient chargées au début du test mais cela perturbait le fonctionnement de l’option `test --keepdb` (la base de données était vide à la fin de tous les tests). Cette modification ne devrait pas avoir d’impacts sur vos tests pour autant que vous n’avez pas personnalisé le fonctionnement interne de `TransactionTestCase`.

### `sqlparse` devient une dépendance obligatoire

To simplify a few parts of Django’s database handling, sqlparse 0.2.2+ is now a required dependency. It’s automatically installed along with Django.

### Alias de `cached_property`

Dans les utilisations telles que

    from django.utils.functional import cached_property

    class A:

        @cached_property
        def base(self):
            return ...

        alias = base

`alias` n’est pas mis en cache. Là où le problème peut être détecté (Python à partir de 3.6), une telle utilisation produit maintenant une exception `TypeError: Cannot assign the same cached_property to two different names ('base' and 'alias').`

Utilisez plutôt ceci

    import operator

    class A:

        ...

        alias = property(operator.attrgetter('base'))

### Permissions pour les modèles mandataires

Les permissions pour les modèles mandataires sont dorénavant créées en utilisant le type de contenu du modèle mandataire plutôt que celui de leur modèle concret. Une migration va mettre à jour les permissions existantes lors de l’exécution de `migrate`.

Dans le site d’administration, la modification est transparente pour les modèles mandataires ayant la même étiquette `app_label` que leur modèle concret. Cependant, dans les anciennes versions, les utilisateurs ayant des permissions pour un modèle mandataire avec une étiquette `app_label` différente de celle du modèle concret n’avaient pas accès au modèle dans le site d’administration. Ceci est maintenant résolu, mais il peut valoir la peine d’auditer les attributions de permissions pour les modèles concernés (`[add|view|change|delete]_monmandataire`) avant la mise à jour pour être certain que les nouveaux accès soient corrects.

Pour terminer, les chaînes de permission des modèles mandataires doivent être mises à jour afin d’utiliser leur propre étiquette `app_label`. Par exemple, pour `app.MonModeleMandataire` héritant de `autre_app.ModeleConcret`, mettez à jour `user.has_perm('autre_app.add_monmodelemandataire')` en `user.has_perm('app.add_monmodelemandataire')`.

### Fusion des fichiers statiques `Media` des formulaires

Les fichiers statiques `Media` des formulaires sont dorénavant fusionnés en utilisant un algorithme de tri topologique, car l’ancien algorithme de fusion par paires était insuffisant à certains égards. Les fichiers CSS et JavaScript qui n’incluent pas leurs dépendances pourraient maintenant être triées de manière incorrecte (là où l’ancien algorithme aurait produit un résultat correct par coïncidence).

Auditer chaque classe `Media` à la recherche de dépendances manquantes. Par exemple, les composants dépendants de `django.jQuery` doivent indiquer `js=['admin/js/jquery.init.js', ...]` dans la déclaration des fichiers statiques de formulaires.

### Divers

- Pour améliorer la lisibilité, le champ de formulaire `UUIDField` affiche dorénavant les valeurs avec tirets, par exemple `550e8400-e29b-41d4-a716-446655440000` au lieu de `550e8400e29b41d4a716446655440000`.

- Avec SQLite, `PositiveIntegerField` et `PositiveSmallIntegerField` incluent dorénavant une contrainte de vérification pour éviter des valeurs négatives dans la base de données. Si des données non valides existent actuellement et que vous lancez une migration qui recrée une table, vous verrez apparaître des erreurs du type `CHECK constraint failed`.

- Par cohérence avec les serveurs WSGI, le client de test définit dorénavant l’en-tête `Content-Length` comme chaîne au lieu de nombre entier.

- La valeur de renvoi de `django.utils.text.slugify()` n’est plus marquée comme HTML sécurisé.

- Le caractère de troncature par défaut utilisé par les filtres de gabarit `urlizetrunc`, `truncatechars`, `truncatechars_html`, `truncatewords` et `truncatewords_html` est désormais le caractère « points de suspension » réel (`…`) au lieu de 3 points. Il se peut que vous deviez mettre à jour certaines comparaisons dans les résultats de tests.

- La prise en charge des chemins d’octets dans le chargeur de gabarits depuis le système de fichiers a été supprimée.

- `django.utils.http.urlsafe_base64_encode()` renvoie dorénavant une chaîne au lieu d’une chaîne d’octets, et `django.utils.http.urlsafe_base64_decode()` n’accepte plus une chaîne d’octets en paramètre.

- La prise en charge de `cx_Oracle` < 6.0 a été abandonnée.

- La version minimum de `mysqlclient` prise en charge est passée de 1.3.7 à 1.3.13.

- La version minimum de SQLite prise en charge est passée de 3.7.15 à 3.8.3.

- Dans le but de fournir des données de requêtes un peu plus sémantiques, `NullBooleanSelect` produit dorénavant les valeurs d”`<option>` `unknown`, `true` et `false` au lieu de `1`, `2` et `3`. Par rétrocompatibilité, les données avec les anciennes valeurs sont toujours acceptées.

- La longueur maximale `max_length` de `Group.name` a passé de 80 à 150 caractères.

- Les tests qui violent les contraintes de base de données différables produisent dorénavant des erreurs avec SQLite 3.20+, tout comme avec les autres moteurs qui gèrent aussi ces contraintes.

- Pour intercepter les erreurs d’utilisation, le client de test `Client` ainsi que `django.utils.http.urlencode()` génèrent maintenant une exception `TypeError` si `None` est transmis comme valeur à coder, car `None` ne peut pas être codé dans les données GET et POST. Transmettez plutôt une chaîne vide, ou omettez entièrement la valeur.

- La commande de gestion `ping_google` utilise dorénavant `https` par défaut au lieu de `http` pour l’URL des cartes de sites. Si votre site est en http, utilisez la nouvelle option `ping_google --sitemap-uses-http`. Si vous employez la fonction `ping_google()`, définissez le nouveau paramètre `sitemap_uses_https` à `False`.

- `runserver` no longer supports `pyinotify` (replaced by Watchman).

- Les fonctions d’agrégat `Avg`, `StdDev` et `Variance` renvoient dorénavant un nombre `Decimal` au lieu d’un `float` si la valeur d’entrée est un nombre `Decimal`.

- Les tests échoueront avec SQLite si les applications sans migrations ont des relations à des applications avec migrations. Ceci a toujours été une limitation documentée depuis l’introduction des migrations dans Django 1.7, mais les échecs sont désormais plus constants. Vous verrez des tests échouant avec des erreurs comme `no such table: <app_label>_<model>`. Cela s’est produit dans plusieurs applications tierces qui ont des modèles sans migrations dans leurs tests. Vous devez ajouter des migrations pour de tel modèles.

- Providing an integer in the `key` argument of the `cache.delete()` or `cache.get()` now raises `ValueError`.

- Plural equations for some languages are changed, because the latest versions from Transifex are incorporated.

  Note

  The ability to handle `.po` files containing different plural equations for the same language was added in Django 2.2.12.

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

### L’attribut `Meta.ordering` des modèles n’affectera plus les requêtes de type `GROUP BY`

L’attribut `Meta.ordering` d’un modèle affectant les requêtes `GROUP BY` (telles que `.annotate().values()`) est une source fréquente de confusion. De telles requêtes émettent dorénavant un avertissement d’obsolescence avec le conseil d’ajouter `order_by()` pour conserver le comportement existant de la requête. `Meta.ordering` sera ignoré dans ces requêtes à partir de Django 3.1.

### Divers

- `django.utils.timezone.FixedOffset` a été rendu obsolète en faveur de `datetime.timezone`.
- L’alias non documenté `QuerySetPaginator` de `django.core.paginator.Paginator` a été rendu obsolète.
- Le champ de modèle et de formulaire `FloatRangeField` dans `django.contrib.postgres` a été rendu obsolète en faveur d’un nouveau nom, `DecimalRangeField`, pour mieux refléter le type de données `numrange` utilisé au niveau de la base de données.
- Le réglage `FILE_CHARSET` est obsolète. À partir de Django 3.1, les fichiers lus depuis le disque doivent être codés en UTF-8.
- `django.contrib.staticfiles.storage.CachedStaticFilesStorage` a été rendu obsolète en raison de ses problèmes insolubles. Remplacez-le plutôt par `ManifestStaticFilesStorage` ou un stockage en nuage de tierce partie.
- `RemoteUserBackend.configure_user()` reçoit dorénavant `request` comme premier paramètre positionnel, s’il l’accepte. La prise en charge des méthodes surchargées n’acceptant pas ce paramètre sera supprimée dans Django 3.1.
- The `SimpleTestCase.allow_database_queries`, `TransactionTestCase.multi_db`, and `TestCase.multi_db` attributes are deprecated in favor of `SimpleTestCase.databases`, `TransactionTestCase.databases`, and `TestCase.databases`. These new attributes allow databases dependencies to be declared in order to prevent unexpected queries against non-default databases to leak state between tests. The previous behavior of `allow_database_queries=True` and `multi_db=True` can be achieved by setting `databases='__all__'`.