# Documentation Django 3.1.9.dev

# Notes de publication de Django 2.1

1er août 2018

Bienvenue dans Django 2.1 !

Ces notes de publications couvrent les nouvelles fonctionnalités, ainsi que certaines modifications non rétro-compatibles dont il faut être au courant lors la mise à jour depuis Django 2.0 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 2.1 requiert Python 3.5, 3.6 ou 3.7. Django 2.0 est la dernière version à prendre en charge Python 3.4. Nous recommandons vivement et nous ne prenons officiellement en charge que la dernière publication de chaque série.

## Quoi de neuf dans Django 2.1

### La permission d’affichage (`view`) des modèles

Une permission d’affichage (`view`) a été ajoutée aux permissions `Meta.default_permissions` des modèles. Les nouvelles permissions seront automatiquement créées lors du lancement de `migrate`.

Cela permet de donner un accès en lecture seule aux modèles dans l’interface d’administration. `ModelAdmin.has_view_permission()` est une nouvelle méthode. L’implémentation est rétrocompatible dans la mesure où il n’est pas nécessaire d’attribuer la permission `view` pour permettre aux utilisateurs qui ont la permission de modification de modifier des objets.

Il existe cependant un certain nombre de considérations sur la rétrocompatibilité.

### Fonctionnalités mineures

#### `django.contrib.admin`

- `ModelAdmin.search_fields` accepte dorénavant des expressions de requête du type `champ__exact`.
- La version intégrée de jQuery a été mise à jour de 2.2.3 vers 3.3.1.
- La nouvelle méthode `ModelAdmin.delete_queryset()` permet la personnalisation du processus de suppression de l’action « Supprimer les objets sélectionnés ».
- Il est dorénavant possible de personnaliser le site d’administration par défaut.
- Le nouvel attribut `ModelAdmin.sortable_by` et la méthode `ModelAdmin.get_sortable_by()` permettent de restreindre les colonnes qui peuvent servir de tri sur la page de liste pour modification.
- L’attribut `admin_order_field` des éléments dans `ModelAdmin.list_display` peut être une expression de requête.
- La nouvelle méthode `ModelAdmin.get_deleted_objects()` permet de personnaliser le processus de suppression de la vue de suppression et de l’action « supprimer la sélection ».
- Les gabarits `actions.html`, `change_list_results.html`, `date_hierarchy.html`, `pagination.html`, `prepopulated_fields_js.html`, `search_form.html` et `submit_line.html` peuvent dorénavant être surchargés par application ou par modèle (en plus de la surcharge globale).
- La liste pour modification et les outils de formulaire de modification d’objet du site d’administration peuvent dorénavant être surchargés par application, par modèle ou globalement avec les gabarits `change_list_object_tools.html` and `change_form_object_tools.html`.
- `InlineModelAdmin.has_add_permission()` reçoit dorénavant l’objet parent comme second paramètre positionnel, `obj`.
- Les actions d’administration peuvent dorénavant indiquer des permissions pour limiter leur disponibilité à certains utilisateurs.

#### `django.contrib.auth`

- `createsuperuser` offre maintenant la possibilité de passer outre les contrôles de validation de mot de passe `AUTH_PASSWORD_VALIDATORS`.

#### `django.contrib.gis`

- La nouvelle méthode `GEOSGeometry.buffer_with_style()` est une version de `buffer()` qui permet de personnaliser le style du tampon.
- `OpenLayersWidget` est maintenant basé sur OpenLayers 4.6.5 (précédemment 3.20.1).

#### `django.contrib.sessions`

- Le réglage `SESSION_COOKIE_SAMESITE` a été ajouté pour définir l’option de cookie `SameSite` pour les cookies de session.

#### Cache

- Le moteur de cache en mémoire locale utilise dorénavant un algorithme de purge LRU (en fonction de la date d’utilisation) plutôt qu’un algorithme pseudo-aléatoire.
- The new `touch()` method of the low-level cache API updates the timeout of cache keys.

#### CSRF

- Le réglage `CSRF_COOKIE_SAMESITE` a été ajouté pour définir l’option de cookie `SameSite` pour les cookies CSRF.

#### Formulaires

- Le composant de `ImageField` est dorénavant produit avec l’attribut HTML `accept="image/*"`.

#### Internationalisation

- La fonction `get_supported_language_variant()` a été ajoutée.
- Les chaînes non traduites des variantes territoriales de langues utilisent dorénavant les traductions de la langue générique. Par exemple, les chaînes `pt_BR` non traduites utilisent les traductions `pt`.

#### Commandes d’administration

- La nouvelle option `inspectdb --include-views` permet de générer des modèles à partir de vues de bases de données.
- La classe `BaseCommand` utilise dorénavant une mise en forme d’aide personnalisée afin que les options standard telles que `--verbosity` ou `--settings` apparaissent en dernier dans le texte d’aide, ce qui octroie une position plus importante aux options spécifiques de la commande.

#### Migrations

- La prise en charge de la sérialisation des objets `functools.partialmethod` a été ajoutée.
- Pour prendre en charge les environnements figés, les migrations peuvent être chargées à partir de fichiers `.pyc`.

#### Modèles

- Les modèles peuvent dorénavant utiliser `__init_subclass__()` de PEP 487.
- Il est dorénavant possible de définir `editable=True` pour un champ `BinaryField` si vous souhaitez l’inclure dans des formulaires de modèles.
- Un certain nombre de nouvelles fonctions texte de base de données ont été ajoutées : `Chr`, `Left`, `LPad`, `LTrim`, `Ord`, `Repeat`, `Replace`, `Right`, `RPad`, `RTrim` et `Trim`.
- La nouvelle fonction `TruncWeek` tronque les objets `DateField` et `DateTimeField` au lundi d’une semaine.
- Il est dorénavant possible d’indiquer la négation d’expressions de requête avec le signe moins.
- `QuerySet.order_by()` et `distinct(*fields)` autorisent dorénavant les transformations de champs.
- `BooleanField` peut dorénavant contenir `null=True`. C’est la méthode conseillée pour remplacer `NullBooleanField`, qui sera probablement rendu obsolète dans une prochaine version.
- La nouvelle méthode `QuerySet.explain()` affiche le plan d’exécution de la base de données pour une requête de base de données `QuerySet`.
- `QuerySet.raw()` prend dorénavant en charge `prefetch_related()`.

#### Requêtes et réponses

- `HttpRequest.get_full_path_info()` a été ajoutée.
- Le paramètre `samesite` a été ajouté à `HttpResponse.set_cookie()` pour permettre de définir l’option de cookie `SameSite`.
- Le nouveau paramètre `as_attachment` de `FileResponse` définit l’en-tête `Content-Disposition` qui pousse les navigateurs à demander à l’utilisateur s’il veut télécharger le fichier. `FileResponse` essaie également de définir les en-têtes `Content-Type` et `Content-Length` lorsque c’est opportun.

#### Gabarits

- Le nouveau filtre `json_script` transforme un objet Python en JSON de manière sûre, enveloppé dans une balise `<script>`, pour utilisation à partir de JavaScript.

#### Tests

- La prise en charge des redirections 307 et 308 pour le `Client` de test a été ajoutée.
- Le class:~django.test.Client de test sérialise dorénavant le dictionnaire de données de requête en JSON si `content_type='application/json'`. Il est possible de personnaliser le codeur JSON à l’aide du paramètre `json_encoder` du client de test.
- La nouvelle méthode `SimpleTestCase.assertWarnsMessage()` est une version simplifiée de `assertWarnsRegex()`.

## Changements incompatibles avec les anciennes versions dans Django 2.1

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

- Pour se conformer à la PEP 249, les exceptions qui concernent l’absence de prise en charge d’une fonctionnalité de base de données sont modifiées de `NotImplementedError` à `django.db.NotSupportedError`.
- Le drapeau de fonctionnalité de base de données `allow_sliced_subqueries` a été renommé en `allow_sliced_subqueries_with_in`.
- `DatabaseOperations.distinct_sql()` now requires an additional `params` argument and returns a tuple of SQL and parameters instead of an SQL string.
- `DatabaseFeatures.introspected_boolean_field_type` a été modifiée, la méthode est devenue propriété.

### `django.contrib.gis`

- La prise en charge de SpatiaLite 4.0 a été supprimée.

### Abandon de la prise en charge de MySQL 5.5

La fin de la prise en charge amont de MySQL 5.5 est en décembre 2018. Django 2.1 prend en charge MySQL 5.6 et plus récent.

### Abandon de la prise en charge de PostgreSQL 9.3

La fin de la prise en charge amont de PostgreSQL 9.3 est en septembre 2018. Django 2.1 prend en charge PostgreSQL 9.4 et plus récent.

### `BCryptPasswordHasher` a été retiré du réglage `PASSWORD_HASHERS` par défaut

SI vous avez utilisé bcrypt avec Django 1.4 ou 1.5 (avant que `BCryptSHA256PasswordHasher` ait été ajouté dans Django 1.6), il est possible que vous ayez certains mots de passe utilisant l’algorithme `BCryptPasswordHasher`.

Vous pouvez vérifier si c’est le cas comme ceci

    from django.contrib.auth import get_user_model
    User = get_user_model()
    User.objects.filter(password__startswith='bcrypt$$')

Si vous souhaitez continuer à autoriser l’emploi de ces mots de passe, vous devrez redéfinir le réglage `PASSWORD_HASHERS` (si ce n’est pas déjà le cas) et inclure `'django.contrib.auth.hashers.BCryptPasswordHasher'`.

### Déplacement de la variable de contexte de gabarit de composant `wrap_label`

Pour corriger l’absence de `<label>` lors de l’utilisation de `RadioSelect` et `CheckboxSelectMultiple` avec `MultiWidget`, la variable de contexte `wrap_label` apparaît dorénavant comme attribut de toutes les options. Par exemple, dans un gabarit personnalisé `input_option.html`, modifiez `{% if wrap_label %}` en `{% if widget.wrap_label %}`.

### Cookies `SameSite`

Les cookies utilisés pour `django.contrib.sessions`, `django.contrib.messages` et la protection CSRF de Django définissent désormais par défaut l’option `SameSite` à `Lax`. Les navigateurs qui respectent cette option n’enverront pas ces cookies dans les requêtes vers une origine différente. Si vous comptez sur le comportement précédent, définissez les réglages `SESSION_COOKIE_SAMESITE` et/ou `CSRF_COOKIE_SAMESITE` à `None`.

### Considérations sur la nouvelle permission d’affichage des modèles (`view`)

#### Les formulaires d’administration personnalisés doivent prendre en compte le cas lecture seule

Avec la nouvelle permission d’affichage (`view`), les formulaires d’administration personnalisés existants peuvent produire des erreurs lorsqu’un utilisateur ne possède pas la permission de modification car le formulaire pourrait accéder à des champs inexistants. Corrigez cela en surchargeant `ModelAdmin.get_form()` et en vérifiant que l’utilisateur possède la permission de modification (`change`) et en renvoyant le formulaire par défaut si ce n’est pas le cas

    class MyAdmin(admin.ModelAdmin):
        def get_form(self, request, obj=None, **kwargs):
            if not self.has_change_permission(request, obj):
                return super().get_form(request, obj, **kwargs)
            return CustomForm

#### La nouvelle permission d’affichage par défaut pourrait permettre des accès non désirés aux vues d’administration

If you have a custom permission with a codename of the form `view_<modelname>`, the new view permission handling in the admin will allow view access to the changelist and detail pages for those models. If this is unwanted, you must change your custom permission codename.

### Divers

- La version minimum de `mysqlclient` prise en charge est passée de 1.3.3 à 1.3.7.
- La prise en charge de SQLite < 3.7.15 a été supprimée.
- Le format de date de la directive `Expires` de `Set-Cookie` a été modifiée pour obéir à la RFC 7231#section-7.1.1.1 au lieu du standard de cookie Netscape. Les tirets présents dans les dates comme `Tue, 25-Dec-2018 22:26:13 GMT` sont supprimés. Cette modification est essentiellement cosmétique sauf peut-être pour de très anciens navigateurs qui n’analysent pas le nouveau format.
- `allowed_hosts` est dorénavant un paramètre obligatoire de l’API privée `django.utils.http.is_safe_url()`.
- L’attribut `multiple` produit par le composant `SelectMultiple` utilise dorénavant la syntaxe booléenne HTML5 plutôt que la forme XHTML `multiple="multiple"`.
- Le code HTML produit par les composants de formulaires n’incluent plus la barre oblique de fermeture pour les éléments vides, par ex. `<br>`. Ceci est incompatible avec XHTML, même si certains composants utilisaient déjà certains aspects de HTML5 comme les attributs booléens.
- La valeur des options vides de `SelectDateWidget` es passée de 0 à la chaîne vide, ce qui pourrait essentiellement demander quelques ajustements dans les tests qui comparent du HTML.
- meth:.User.has_usable_password et la fonction `is_password_usable()` ne renvoient plus `False` si le mot de passe vaut `None` ou une chaîne vide, ou si le mot de passe utilise un algorithme absent du réglage `PASSWORD_HASHERS`. Ce comportement non documenté était une régression dans Django 1.6 et empêchait les utilisateurs ayant de tels mots de passe de demander une réinitialisation de leur mot de passe. Examinez votre code pour confirmer que votre utilisation de cette API ne compte pas sur l’ancien comportement.
- Comme les migrations sont dorénavant aussi chargées à partir de fichiers `.pyc`, il pourrait être nécessaire de les supprimer si vous travaillez dans un environnement mixte Python 2 et Python 3.
- L’emploi de `None` comme valeur de recherche pour `JSONField` trouve dorénavant les objets qui ont la clé indiquée avec la valeur nulle plutôt que les objets qui n’ont pas cette clé.
- La classe CSS d’administration `field-box` a été renommée en `fieldBox` pour éviter des conflits avec la classe attribuée aux champs de modèle nommés `box`.
- Since the admin’s `actions.html`, `change_list_results.html`, `date_hierarchy.html`, `pagination.html`, `prepopulated_fields_js.html`, `search_form.html`, and `submit_line.html` templates can now be overridden per app or per model, you may need to rename existing templates with those names that were written for a different purpose.
- `QuerySet.raw()` place désormais en mémoire cache ses résultats tout comme les jeux de requête normaux. Utilisez `iterator()` si vous voulez éviter le cache.
- La méthode de routeur de base de données `allow_relation()` est appelée dans plus de situations. Les routeurs mal écrits pourraient avoir besoin d’être mis à jour en conséquence.
- Les traductions ne sont plus désactivées avant de lancer les commandes d’administration. Si votre commande personnalisée a besoin de fonctionner sans les traductions (par exemple pour insérer du contenu non traduit dans la base de données), utilisez le nouveau décorateur @no_translations.
- Les commandes d’administration n’autorisent plus les formes abrégées des paramètres `--settings` et `--pythonpath`.
- La constante privée `django.db.models.sql.constants.QUERY_TERMS` a été supprimée. Les méthodes `get_lookup()` et `get_lookups()` de l”API d’inscription des recherches peuvent constituer de bonnes alternatives. Comparées à la constante `QUERY_TERMS`, elles permettent à votre code de tenir aussi compte des recherches personnalisées qui ont été inscrites.
- La compatibilité avec `py-bcrypt` a été supprimée car ce paquet n’est plus maintenu. Utilisez bcrypt à la place.

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

### Divers

- La fonction GIS `ForceRHR` a été rendue obsolète en faveur de la nouvelle fonction `ForcePolygonCW`.
- `django.utils.http.cookie_date()` a été rendue obsolète en faveur de `http_date()`, qui respecte le format de la RFC la plus récente.
- `{% load staticfiles %}` et `{% load admin_static %}` sont obsolètes en faveur de `{% load static %}`, qui remplit le même rôle.
- `django.contrib.staticfiles.templatetags.static()` est obsolète en faveur de `django.templatetags.static.static()`.
- La prise en charge des méthodes `InlineModelAdmin.has_add_permission()` qui n’acceptent pas `obj` comme second paramètre positionnel sera supprimée dans Django 3.0.

## Fonctionnalités supprimées dans Django 2.1

Ces fonctionnalités ont atteint la fin de leur cycle d’obsolescence et sont supprimées dans Django 2.1. Voir Fonctionnalités rendues obsolètes dans Django 1.11 pour les détails, ainsi que pour savoir comment supprimer l’utilisation de ces fonctionnalités.

- `contrib.auth.views.login()`, `logout()`, `password_change()`, `password_change_done()`, `password_reset()`, `password_reset_done()`, `password_reset_confirm()` et `password_reset_complete()` ont été supprimés.
- Le paramètre `extra_context` de `contrib.auth.views.logout_then_login()` a été supprimé.
- `django.test.runner.setup_databases()` a été supprimée.
- `django.utils.translation.string_concat()` a été supprimée.
- `django.core.cache.backends.memcached.PyLibMCCache` ne prend plus en charge la transmission des réglages de comportement `pylibmc` comme attributs de premier niveau des `OPTIONS`.
- Le paramètre `host` de `django.utils.http.is_safe_url()` a été supprimé.
- Le masquage des exceptions produites lors du rendu de la balise de gabarit `{% include %}` a été supprimé.
- `DatabaseIntrospection.get_indexes()` a été supprimée.
- La méthode `authenticate()` des moteurs d’authentification exige `request` comme premier paramètre positionnel.
- Le décorateur `django.db.models.permalink()` a été supprimé.
- Le réglage `USE_ETAGS` a été supprimé. `CommonMiddleware` et `django.utils.cache.patch_response_headers()` ne créent plus d’ETags.
- L’attribut `Model._meta.has_auto_field` a été supprimé.
- La prise en charge de `url()` des drapeaux en ligne dans les groupes d’expressions régulières (`(?i)`, `(?L)`, `(?m)`, `(?s)`, and `(?u)`) a été supprimée.
- La prise en charge des méthodes `Widget.render()` sans le paramètre `renderer` a été supprimée.