# Documentation Django 3.1.9.dev

# Notes de publication de Django 1.9

1er décembre 2015

Bienvenue dans Django 1.9 !

These release notes cover the new features, as well as some backwards incompatible changes you’ll want to be aware of when upgrading from Django 1.8 or older versions. We’ve dropped some features that have reached the end of their deprecation cycle, and we’ve begun the deprecation process for some features.

Voir le guide Mise à jour de Django à une version plus récente si vous mettez à jour un projet existant.

## Compatibilité Python

Django 1.9 requiert Python 2.7, 3.4 ou 3.5. Nous recommandons vivement et nous ne prenons officiellement en charge que la dernière publication de chaque série.

La série Django 1.8 est la dernière à prendre en charge Python 3.2 et 3.3.

## Quoi de neuf dans Django 1.9

### Lancement d’actions après le commit d’une transaction

Le nouveau point d’entrée `on_commit()` permet de lancer des actions après qu’une transaction de base de données a été validée avec succès. C’est utile pour des tâches telles que l’envoi de courriels de notification, la création de tâches à placer dans une file ou pour l’invalidation des caches.

Cette fonctionnalité provenant du paquet django-transaction-hooks a été intégrée dans Django.

### Validation des mots de passe

Django offre maintenant la validation de mots de passe pour aider à prévenir l’utilisation de mots de passe faibles par les utilisateurs. La validation est intégrée aux formulaires de changement et de réinitialisation des mots de passe et s’intègre facilement dans n’importe quel autre code. La validation est effectuée par un ou plusieurs validateurs, configurés dans le nouveau réglage `AUTH_PASSWORD_VALIDATORS`.

Quatre validateurs sont inclus dans Django ; ceux-ci peuvent imposer une longueur minimale, comparer le mot de passe à des attributs de l’utilisateur tels que leur nom, s’assurer que les mots de passe ne soient pas entièrement numériques, ou comparer avec une liste de mots de passe communs. Vous pouvez combiner plusieurs validateurs, et certains validateurs possèdent des options de configuration propres. Par exemple, vous pouvez choisir de fournir une liste personnalisée de mots de passe communs. Chaque validateur fournit un texte d’aide pour expliquer ses exigences à l’utilisateur.

Par défaut, aucune validation n’est effectuée et tous les mots de passe sont acceptés. Si vous ne mettez pas de contenu dans `AUTH_PASSWORD_VALIDATORS`, vous ne verrez aucun changement. Dans les nouveaux projets créés avec le gabarit `startproject` par défaut, un ensemble simple de validateurs est activé. Pour activer la validation de base dans les formulaires d’authentification de Django dans votre projet, vous pouvez définir, par exemple :

    AUTH_PASSWORD_VALIDATORS = [
        {
            'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
        },
        {
            'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
        },
    ]

Voir Validation des mots de passe pour plus de détails.

### Classes mixins de permissions dans les vues fondées sur les classes

Django est dorénavant livré avec les classes mixins `AccessMixin`, `LoginRequiredMixin`, `PermissionRequiredMixin` et `UserPassesTestMixin` pour fournir la fonctionnalité de `django.contrib.auth.decorators` pour les vues fondées sur les classes. Ces classes proviennent ou s’inspirent en tout cas du projet django-braces.

There are a few differences between Django’s and `django-braces`” implementation, though:

- L’attribut `raise_exception` ne peut valoir que `True` ou `False`. Les exceptions ou objets exécutables personnalisés ne sont pas pris en charge.
- La méthode `handle_no_permission()` n’accepte pas de paramètre `request`. La requête en cours est disponible dans `self.request`.
- La fonction personnalisée `test_func()` de `UserPassesTestMixin` n’accepte pas de paramètre `user`. La requête en cours est disponible dans `self.request.user`.
- L’attribut `permission_required` accepte une chaîne (définissant une permission) ou une liste de chaînes (définissant plusieurs permissions) qui doivent être accordées pour autoriser l’accès.
- Le nouvel attribut `permission_denied_message` permet de transmettre un message à l’exception `PermissionDenied`.

### Nouveau style pour `contrib.admin`

L’interface d’administration présente un nouvel aspect moderne et en aplat avec de nouvelles icônes SVG qui s’affichent parfaitement sur des écrans haute densité. Elle garantit toujours une expérience pleinement fonctionnelle avec les navigateurs de niveau A de YUI. Les navigateurs plus anciens peuvent parfois se comporter en mode dégradé acceptable.

### Lancement des tests en parallèle

The `test` command now supports a `--parallel` option to run a project’s tests in multiple processes in parallel.

Chaque processus travaille avec sa propre base de données. Vous devez vous assurer que les différents cas de test n’accèdent pas aux mêmes ressources. Par exemple, les cas de test qui touchent au système de fichiers devraient créer un répertoire temporaire pour leur propre usage.

Cette option est activée par défaut pour la propre suite de tests de Django pour autant que :

- le système d’exploitation le prend en charge (tous sauf Windows)
- le moteur de base de données le prend en charge (tous les moteurs intégrés sauf Oracle)

### Fonctionnalités mineures

#### `django.contrib.admin`

- Les vues d’administration possèdent maintenant des attributs `model_admin` ou `admin_site`.
- L’URL de la vue de modification du site d’administration a été modifiée (de `/admin/<app>/<modèle>/<pk>/` par défaut à `/admin/<app>/<modèle>/<pk>/change/`). Cela ne devrait pas affecter votre application sauf si vous avez codé en dur des URL d’administration. Dans ce cas, remplacez ces liens de préférence par la résolution inverse des URL d’administration. Notez que l’ancienne URL redirige toujours vers la nouvelle par rétrocompatibilité, mais cela pourrait cesser dans une version future.
- `ModelAdmin.get_list_select_related()` a été ajoutée pour permettre de modifier les valeurs `select_related()` utilisées dans la requête de la liste pour modification du site d’administration en fonction de la requête.
- La variable de contexte `available_apps`, qui contient la liste des applications disponibles pour l’utilisateur actuel, a été ajoutée à la méthode `AdminSite.each_context()`.
- `AdminSite.empty_value_display` et `ModelAdmin.empty_value_display` ont été ajoutés pour surcharger l’affichage de valeurs vides dans la liste pour modification du site d’administration. Il est aussi possible de personnaliser la valeur pour chaque champ.
- Des événements jQuery ont été ajoutés lorsqu’un sous-formulaire est ajouté ou enlevé sur la page contenant le formulaire de modification.
- Le composant de sélection de l’heure inclut une option « 18:00 » par cohérence avec la présence d’options prédéfinies toutes les 6 heures.
- La génération de « slugs » en JavaScript prend dorénavant en charge les caractères roumains.

#### `django.contrib.admindocs`

- La section modèles de `admindocs` documente dorénavant aussi les méthodes qui acceptent des paramètres, plutôt que de les ignorer.

#### `django.contrib.auth`

- Le nombre d’itérations par défaut du hachage des mots de passe PBKDF2 a été augmenté de 20%. Cette modification rétrocompatible n’affecte pas ceux qui ont créé une sous-classe de `django.contrib.auth.hashers.PBKDF2PasswordHasher` pour modifier la valeur par défaut.
- La classe `BCryptSHA256PasswordHasher` met dorénavant les mots de passe à jour lorsque son attribut `rounds` est modifié.
- `AbstractBaseUser` et `BaseUserManager` ont été déplacés vers un nouveau module `django.contrib.auth.base_user` afin qu’ils puissent être importés sans devoir inclure `django.contrib.auth` dans `INSTALLED_APPS` (ce qui générait une avertissement d’obsolescence dans les anciennes versions et qui n’est plus pris en charge depuis Django 1.9).
- Le paramètre `permission` de `permission_required()` accepte toutes les variantes d’éléments itérables, pas seulement les listes et les tuples.
- La nouvelle classe `PersistentRemoteUserMiddleware` rend possible l’exploitation de `REMOTE_USER` dans les configurations où cet en-tête n’est renseigné que sur les pages de connexion et non sur les autres requêtes de la session.
- The `django.contrib.auth.views.password_reset()` view accepts an `extra_email_context` parameter.

#### `django.contrib.contenttypes`

- Il est maintenant possible d’utiliser `order_with_respect_to` avec une relation `GenericForeignKey`.

#### `django.contrib.gis`

- Toutes les méthodes `GeoQuerySet` ont été rendues obsolètes et remplacées par des fonctions de base de données équivalentes. Dès que les anciennes méthodes auront été remplacées dans votre code, il est alors même possible d’enlever le gestionnaire spécial `GeoManager` de vos classes de modèles géographiques.
- L’interface GDAL prend désormais en charge l’instanciation d”objets GDALRaster à base de fichiers et en mémoire à partir de données brutes. Les propriétés matricielles telles que la projection ou les valeurs de pixels peuvent maintenant être modifiées.
- Pour les utilisateurs de PostGIS, le nouveau champ `RasterField` permet de stocker des objets GDALRaster. Il prend en charge la création automatique d’index spatial et la reprojection lors de l’enregistrement d’un modèle. Il ne supporte pas encore l’interrogation spatiale.
- La nouvelle méthode `GDALRaster.warp()` permet de déformer une structure matricielle en indiquant des propriétés cibles telles que l’origine, la largeur, la hauteur ou la taille de pixel (parmi d’autres).
- La nouvelle méthode `GDALRaster.transform()` permet de transformer une structure matricielle dans un autre système de référence spatiale en indiquant un code `srid` cible.
- La nouvelle classe `GeoIP2` permet d’exploiter les bases de données GeoLite2 de MaxMind qui incluent la prise en charge des adresses IPv6.
- The default OpenLayers library version included in widgets has been updated from 2.13 to 2.13.1.

#### `django.contrib.postgres`

- La prise en charge de l’interrogation `rangefield.contained_by` a été ajoutée pour certains champs intégrés qui correspondent aux champs d’intervalle.
- Le champ `JSONField` a été ajouté.
- Des Fonctions d’agrégation spécifiques à PostgreSQL ont été ajoutées.
- La fonction de base de données `TransactionNow` a été ajoutée.

#### `django.contrib.sessions`

- Le modèle de session et les classes `SessionStore` pour les moteurs `db` et `cached_db` ont été refactorisés pour permettre de bâtir sur ceux-ci un moteur de session personnalisé fondé sur une base de données. Voir Extension des moteurs de sessions s’appuyant sur une base de données pour plus de détails.

#### `django.contrib.sites`

- `get_current_site()` gère maintenant le cas où `request.get_host()` renvoie `domaine:port`, par exemple `exemple.com:80`. Si la recherche échoue parce que l’hôte ne correspond pas à un enregistrement dans la base de données et que l’hôte dispose d’un port, la recherche est relancée sans le port et uniquement avec la partie du domaine.

#### `django.contrib.syndication`

- Plusieurs annexes par élément de flux sont maintenant possibles. Si plusieurs annexes sont définies pour un flux RSS, une exception est produite car les flux RSS, au contraire des flux Atom, ne gèrent pas plusieurs annexes par élément de flux.

#### Cache

- `django.core.cache.backends.base.BaseCache` possède maintenant une méthode `get_or_set()`.
- `django.views.decorators.cache.never_cache()` envoie maintenant des en-têtes plus persuasifs (`no-cache, no-store, must-revalidate` ont été ajoutés à `Cache-Control`) puor mieux empêcher le cache. Ceci a aussi été ajouté à Django 1.8.8.

#### CSRF

- Le nom d’en-tête de requête utilisé pour l’authentification CSRF peut être personnalisé avec `CSRF_HEADER_NAME`.
- L’en-tête de référant CSRF est maintenant validée en fonction du réglage `CSRF_COOKIE_DOMAIN` si celui-ci est défini. Voir Fonctionnement pour plus de détails.
- Le nouveau réglage `CSRF_TRUSTED_ORIGINS` donne la possibilité d’autoriser des requêtes non sûres (par ex. `POST`) d’origine croisée sur HTTPS.

#### Moteurs de base de données

- Le moteur PostgreSQL (`django.db.backends.postgresql_psycopg2`) est également disponible en tant que `django.db.backends.postgresql`. L’ancien nom continuera d’être disponible par rétro-compatibilité.

#### Stockage de fichier

- `Storage.get_valid_name()` est dorénavant appelée lorsque `upload_to` est un objet exécutable.
- `File` possède maintenant la méthode `seekable()` avec Python 3.

#### Formulaires

- `ModelForm` accepte la nouvelle option `Meta` `field_classes` pour personnaliser les types de champs. Voir Surcharge des champs par défaut pour plus de détails.
- Vous pouvez maintenant définir l’ordre dans lequel les champs de formulaire sont affichés en vous servant de l’attribut `field_order`, du paramètre de constructeur `field_order` ou de la méthode `order_fields()`.
- Un préfixe de formulaire peut être défini dans une classe de formulaire, non seulement lors de l’instanciation du formulaire. Voir Préfixes de formulaires pour plus de détails.
- Vous pouvez maintenant définir des paramètres nommés que vous souhaitez transmettre au constructeur des formulaires dans un jeu de formulaires.
- `SlugField` accepte dorénavant un paramètre `allow_unicode` pour autoriser les caractères Unicode dans les « slugs ».
- `CharField` accepte maintenant un paramètre `strip` pour épurer les données saisies d’éventuelles espaces initiales ou finales. Comme la valeur par défaut est `True`, le comportement est donc différent des versions précédentes.
- Les champs de formulaire acceptent maintenant un paramètre `disabled` ce qui provoque l’affichage d’un composant de champ désactivé dans les navigateurs.
- Il est maintenant possible de personnaliser les champs de formulaire liés aux données en surchargeant la méthode `get_bound_field()`.

#### Vues génériques

- Les vues fondées sur les classes générées par `as_view()` possèdent maintenant les attributs `view_class` et `view_initkwargs`.
- `method_decorator()` peut maintenant être utilisée avec une liste ou un tuple de décorateurs. On peut aussi l’utiliser pour décorer des classes au lieu de méthodes.

#### Internationalisation

- La vue `django.views.i18n.set_language()` redirige maintenant correctement vers les URL traduites lorsqu’elles sont disponibles.
- The `django.views.i18n.javascript_catalog()` view now works correctly if used multiple times with different configurations on the same page.
- La fonction `django.utils.timezone.make_aware()` possède un nouveau paramètre `is_dst` pour aider à résoudre les heures ambiguës lors des passages heure d’été / heure d’hiver.
- Les variantes de langue prises en charge par gettext peuvent maintenant être utilisées. Elles sont généralement utilisées pour des langues qui s’écrivent dans différentes écritures, par exemple latin et cyrillique (comme par ex. `be@latin`).
- Added the `django.views.i18n.json_catalog()` view to help build a custom client-side i18n library upon Django translations. It returns a JSON object containing a translations catalog, formatting settings, and a plural rule.
- L’attribut `name_translated` a été ajouté à l’objet renvoyé par la balise de gabarit `get_language_info`. Un filtre de gabarit similaire a aussi été ajouté : `language_name_translated`.
- Vous pouvez maintenant exécuter `compilemessages` à partir du répertoire racine d’un projet et elle trouvera tous les fichiers de messages qui ont été créés par `makemessages`.
- `makemessages` appelle maintenant xgettext une fois par répertoire de langue au lieu d’une fois par fichier traduisible. Cela accélère la construction des catalogues de traduction.
- `blocktrans` permet d’attribuer son résultat à une variable avec `asvar`.
- Deux nouvelles langues sont disponibles : l’espagnol colombien et le gaélique écossais.

#### Commandes d’administration

- La nouvelle commande `sendtestemail` permet d’envoyer un courriel de test pour confirmer facilement que l’envoi de courriels au travers de Django fonctionne.
- Pour améliorer la lisibilité du code SQL généré par la commande `sqlmigrate`, le code SQL généré pour chaque opération de migration est précédé par la description de l’opération.
- Le résultat produit par la commande `dumpdata` est maintenant ordonné de manière déterministe. De plus, lorsque l’option `--output` est donnée, la commande affiche aussi une barre de progression dans le terminal.
- La commande `createcachetable` offre maintenant une option `--dry-run` pour afficher le code SQL au lieu de l’exécuter.
- La commande `startapp` crée un fichier `apps.py`. Comme celui-ci ne contient pas `default_app_config` (une API découragée), vous devez indiquer le chemin de la configuration d’application dans `INSTALLED_APPS`, par exemple `'polls.apps.PollsConfig'`, pour que la configuration soit utilisée (au lieu d’un simple `'polls'`).
- Avec le moteur PostgreSQL, la commande `dbshell` peut se connecter à la base de données en utilisant le mot de passe provenant du fichier des réglages (au lieu de devoir le saisir manuellement).
- Le paquet `django` peut être exécuté comme un script, comme par exemple `python -m django`, ce qui produira le même comportement que `django-admin`.
- Les commandes d’administration possédant l’option `--noinput` acceptent maintenant également `--no-input` comme alias de cette option.

#### Migrations

- Initial migrations are now marked with an `initial = True` class attribute which allows `migrate --fake-initial` to more easily detect initial migrations.

- La prise en charge de la sérialisation d’instances `functools.partial` et `LazyObject` a été ajoutée.

- Lorsqu’on indique la valeur `None` pour un élément dans `MIGRATION_MODULES`, Django considère que cette application ne possède pas de migration.

- Lors de l’application des migrations, l’étape « rendu des états de modèles » qui apparaît lors de l’exécution des migrations avec une verbosité de 2 ou plus élevée calcule maintenant uniquement les états des migrations qui ont déjà été appliquées. Les états de modèles des migrations en cours d’application sont générés à la demande, ce qui réduit drastiquement la quantité de mémoire nécessaire.

  Cependant, cette amélioration n’est pas disponible lors de l’inversion des migrations et, dans ce cas, il est toujours nécessaire de précalculer et de stocker les états des migrations intermédiaires.

  Cette amélioration est aussi la cause de la non prise en charge par Django des plans de migration mixtes. Ces plans mixtes consistent en une liste de migrations où certaines doivent être appliquées et d’autres inversées. Cela n’a jamais été officiellement pris en charge et il n’existait pas d’API publique qui s’appuyait sur ce comportement.

- La commande `squashmigrations` accepte dorénavant la possibilité d’indiquer la migration de départ à partir de laquelle les migrations sont fusionnées.

#### Modèles

- `QuerySet.bulk_create()` fonctionne maintenant aussi pour des modèles mandataires.
- La configuration des bases de données contient une nouvelle option `TIME_ZONE` pour interagir avec les bases de données qui stockent les dates/heures en heure locale et qui ne prennent pas en charge les fuseaux horaires lorsque `USE_TZ` vaut `True`.
- La méthode `RelatedManager.set()` a été ajoutée aux gestionnaires de relations créés par les champs `ForeignKey`, `GenericForeignKey` et `ManyToManyField`.
- La méthode `add()` du côté opposé d’une clé étrangère possède maintenant un paramètre `bulk` pour permettre l’exécution d’une seule requête quel que soit le nombre d’objets à ajouter, au lieu d’exiger une requête par objet.
- Le paramètre `keep_parents` a été ajouté à `Model.delete()` pour permettre de ne supprimer que les données « enfant » d’un modèle qui hérite d’autres tables.
- `Model.delete()` et `QuerySet.delete()` renvoient le nombre d’objets supprimés.
- Un contrôle système a été ajouté pour empêcher de définir à la fois `Meta.ordering` et `order_with_respect_to` pour le même modèle.
- Les interrogations de `date et d'heure` peuvent être suivies d’autres interrogations (comme `exact`, `gt`, `lt`, etc.). Par exemple, `Entry.objects.filter(pub_date__month__gt=6)`.
- Les interrogations d’heure (heure, minute, seconde) sont maintenant prises en charge par `TimeField` pour tous les moteurs de base de données. Sauf pour SQLite, ces interrogations étaient déjà disponibles depuis Django 1.7, mais non documentées.
- Le paramètre `output_field` a été ajouté pour permettre l’agrégation `Avg` sur des colonnes non numériques, comme par exemple `DurationField`.
- L’interrogation `date` a été ajoutée à `DateTimeField` pour permettre d’interroger le champ par la seule portion de date.
- Les fonctions de base de données `Greatest` et `Least` ont été ajoutées.
- La fonction de base de données `Now` a été ajoutée ; celle-ci renvoie la date et l’heure courantes.
- `Transform` est dorénavant une sous-classe de Func(), ce qui permet aux objets `Transform` d’être utilisés dans la partie droite d’une expression, comme pour les objets `Func` normaux. Cela permet d’inscrire certaines fonctions de base de données comme `Length`, `Lower` et `Upper` en tant que transformations.
- `SlugField` accepte dorénavant un paramètre `allow_unicode` pour autoriser les caractères Unicode dans les « slugs ».
- Il est maintenant possible de référencer les annotations dans `QuerySet.distinct()`.
- Avec SQLite, `connection.queries` affiche les requêtes avec les paramètres substitués.
- Les expressions de requête peuvent maintenant être utilisées lors de la création de nouvelles instances de modèles avec `save()`, `create()` et `bulk_create()`.

#### Requêtes et réponses

- Tant que `HttpResponse.reason_phrase` n’est pas explicitement défini, sa valeur est maintenant déterminée par la valeur actuelle de `HttpResponse.status_code`. La modification de `status_code` en dehors du constructeur modifie également la valeur de `reason_phrase`.
- La vue de débogage affiche maintenant les détails de la chaîne des exceptions avec Python 3.
- Les vues d’erreur 40x par défaut acceptent maintenant un second paramètre positionnel, l’exception qui a déclenché l’erreur.
- Les gestionnaires des vues d’erreur prennent maintenant en charge `TemplateResponse`, qui sont couramment utilisées avec les vues fondées sur les classes.
- Les exceptions générées par la méthode `render()` sont maintenant aussi transmises à la méthode `process_exception()` de chaque intergiciel.
- Les intergiciels de requête peuvent maintenant définir `HttpRequest.urlconf` à `None` pour annuler tout changement effectué par un intergiciel précédent et revenir à la valeur `ROOT_URLCONF` de départ.
- Le contrôle `DISALLOWED_USER_AGENTS` dans `CommonMiddleware` génère maintenant une exception `PermissionDenied` au lieu de `HttpResponseForbidden` afin que la vue `handler403` soit appelée.
- `HttpRequest.get_port()` a été ajoutée pour récupérer le port d’origine de la requête.
- Le paramètre `json_dumps_params` a été ajouté à `JsonResponse` pour permettre la transmission de paramètres nommés à l’appel `json.dumps()` utilisé pour produire la réponse.
- L’intergiciel `BrokenLinkEmailsMiddleware` ignore dorénavant les erreurs 404 lorsque le référant est égal à l’URL demandée. Pour contourner le contrôle du référant vide déjà implémenté, certains robots Web définissent le référant à la même valeur que l’URL demandée.

#### Gabarits

- Les balises de gabarit créés avec l’utilitaire `simple_tag()` peuvent maintenant stocker leur résultat dans une variable de gabarit en utilisant le paramètre `as`.
- La méthode `Context.setdefault()` a été ajoutée.
- Le journaliseur django.template a été ajouté et reçoit les messages suivants :
  - Un message de niveau `DEBUG` pour les variables de contexte manquantes.
  - Un message de niveau `WARNING` pour les exceptions non interceptées générées pendant le rendu d’une balise `{% include %}` lorsque le mode débogage est désactivé (utile car `{% include %}` réduit au silence l’exception et renvoie une chaîne vide).
- La balise de gabarit `firstof` permet de stocker son résultat dans une variable avec `as`.
- `Context.update()` peut maintenant être utilisée comme gestionnaire de contexte.
- Les chargeurs de gabarit de Django peuvent maintenant étendre des gabarits de manière récursive.
- Le gabarit « postmortem » de la page de débogage inclut dorénavant un résultat pour chaque moteur de gabarit installé.
- L”intégration de la page de débogage pour les moteurs de gabarit personnalisés a été ajoutée.
- Il est maintenant possible d’inscrire explicitement des bibliothèques et des éléments intégrés pour le moteur `DjangoTemplates` au moyen du réglage de gabarit `OPTIONS`.
- Les filtres `timesince` et `timeuntil` ont été améliorés pour tenir compte des années bissextiles pour de grands intervalles de temps.
- La balise `include` met dorénavant en cache les objets gabarits analysés durant le processus de rendu des gabarits, accélérant la réutilisation dans des endroits comme les boucles `for`.

#### Tests

- La méthode `json()` a été ajoutée aux réponses du client de test pour donner accès au corps de la réponse en format JSON.
- La méthode `force_login()` a été ajoutée au client de test. Utilisez cette méthode pour simuler l’effet d’un utilisateur se connectant au site tout en évitant de passer par les étapes d’authentification et de vérification de `login()`.

#### URL

- Les assertions de type « lookaround » sont maintenant autorisées dans les expressions régulières des motifs d’URL.
- The application namespace can now be set using an `app_name` attribute on the included module or object. It can also be set by passing a 2-tuple of (<list of patterns>, <application namespace>) as the first argument to `include()`.
- Des contrôles système ont été ajoutés pour les erreurs courantes dans les motifs d’URL.

#### Validateurs

- `django.core.validators.int_list_validator()` a été ajouté pour générer des validateurs de chaînes contenant des nombres entiers séparés par un caractère personnalisé.
- `EmailValidator` limite dorénavant la longueur des parties de noms de domaine à 63 caractères, en accord avec la RFC 1034.
- `validate_unicode_slug()` a été ajouté pour valider des « slugs » pouvant contenir des caractères Unicode.

## Changements incompatibles avec les anciennes versions dans Django 1.9

Avertissement

En plus des modifications détaillées dans cette section, prenez soin de parcourir les Features removed in 1.9 énumérant les fonctionnalités ayant terminé leur cycle d’obsolescence et qui ont donc été supprimées. Si vous n’avez pas mis à jour votre code dans le temps imparti par la période d’obsolescence d’une certaine fonctionnalité, sa suppression pourrait apparaître comme un changement incompatible avec les anciennes versions.

### API de moteur de base de données

- Quelques nouveaux tests reposent sur la capacité du moteur d’examiner les valeurs par défaut des colonnes (renvoyant le résultat dans `Field.default`). Vous pouvez définir la fonctionnalité de base de données `can_introspect_default` à `False` si votre moteur ne permet pas cette introspection. Vous pouvez passer en revue la mise en œuvre sur les moteurs inclus dans Django pour référence (#24245).

- Il est déconseillé d’enregistrer un adaptateur ou un convertisseur global au niveau du module DB-API pour gérer les informations de fuseau horaire des valeurs `datetime` passées comme paramètres de requête ou renvoyés comme résultats de requêtes avec des bases de données qui ne prennent pas en charge les fuseaux horaires. Cela peut engendrer des conflits avec d’autres bibliothèques.

  La méthode recommandée pour ajouter un fuseau horaire aux valeurs `datetime` obtenues de la base de données est d’inscrire un convertisseur pour les champs `DateTimeField` dans `DatabaseOperations.get_db_converters()`.

  La fonctionnalité de base de données `needs_datetime_string_cast` a été supprimée. Les moteurs de base de données qui la définissent doivent inscrire un convertisseur à la place, comme expliqué ci-dessus.

- Les méthodes `DatabaseOperations.value_to_db_<type>()` ont été renommées en `adapt_<type>field_value()` par cohérence avec les méthodes `convert_<type>field_value()`.

- Pour utiliser la nouvelle interrogation `date`, les moteurs de base de données tiers pourraient devoir implémenter la méthode `DatabaseOperations.datetime_cast_date_sql()`.

- La méthode `DatabaseOperations.time_extract_sql()` a été ajoutée. Elle appelle la méthode existante `date_extract_sql()`. Cette méthode est surchargée par le moteur SQLite pour ajouter les interrogations horaires (heure, minute, seconde) aux champs `TimeField`. Certains moteurs de base de données tiers pourraient avoir à faire de même.

- La méthode `DatabaseOperations.datetime_cast_sql()` (à ne pas confondre avec `DatabaseOperations.datetime_cast_date_sql()` citée ci-dessus) a été supprimée. Cette méthode étaient utilisée pour mettre en forme les dates avec Oracle bien avant la version 1.0, mais n’a pas été surchargée par d’autres moteurs intégrés durant des années, et n’a pas non plus été appelée depuis d’autres endroits du code ou des tests de Django.

- Afin de prendre en charge la parallélisation des tests, il faut implémenter la méthode `DatabaseCreation._clone_test_db()` et définir `DatabaseFeatures.can_clone_databases = True`. Il peut être nécessaire d’ajuster `DatabaseCreation.get_test_db_clone_settings()`.

### Les réglages par défaut qui étaient des tuples sont maintenant des listes

Les réglages par défaut dans `django.conf.global_settings` comportaient aussi bien des listes que des tuples. Tous les réglages qui étaient précédemment des tuples sont maintenant des listes.

### L’attribut `is_usable` des chargeurs de gabarit a été supprimé

Les chargeurs de gabarit de Django exigeanient auparavant la présence d’un attribut `is_usable`. Si un chargeur était configuré dans le réglage des gabarits et que cet attribut valait `False`, le chargeur était ignoré en silence. En pratique, ce n’était utilisé que par le chargeur « egg » pour détecter si setuptools était installé. Cet attribut `is_usable` est maintenant supprimé et le chargeur « egg » échoue au moment de l’exécution si setuptools n’est pas installé.

### Attribution directe d’un ensemble d’objets liés

Direct assignment of related objects in the ORM used to perform a `clear()` followed by a call to `add()`. This caused needlessly large data changes and prevented using the `m2m_changed` signal to track individual changes in many-to-many relations.

Direct assignment now relies on the new `set()` method on related managers which by default only processes changes between the existing related set and the one that’s newly assigned. The previous behavior can be restored by replacing direct assignment by a call to `set()` with the keyword argument `clear=True`.

`ModelForm`, et donc aussi `ModelAdmin`, se basent en interne sur l’attribution directe pour les relations plusieurs-à-plusieurs et par conséquent utilisent maintenant le nouveau comportement.

### Les chargeurs de gabarits basés sur le système de fichiers interceptent plus précisément les exceptions

Lors de l’utilisation des chargeurs de gabarits `filesystem.Loader` ou `app_directories.Loader`, les version précédentes de Django généraient une erreur `TemplateDoesNotExist` si une source de gabarit existait mais qu’elle n’était pas lisible. Cela pouvait se produire dans diverses circonstances, comme par exemple si Django n’avait pas les permissions d’ouvrir le fichier ou que la source du gabarit était un répertoire. Dorénavant, Django ne masque une exception que si la source du gabarit n’existe pas. Dans tous les autres cas, ce sera l’exception `IOError` d’origine qui sera générée.

### Les redirections HTTP ne doivent plus forcément être des URI absolues

Les redirections relatives ne sont plus converties en URI absolues. La RFC 2616 exige que l’en-tête `Location` des réponses de redirection soit une URI absolue, mais cette norme a été remplacée par la RFC 7231 qui autorise les URI relatives dans `Location`, reconnaissant ainsi la pratique réelle des agents utilisateurs, dont presque tous acceptent cette façon de faire.

Consequently, the expected URLs passed to `assertRedirects` should generally no longer include the scheme and domain part of the URLs. For example, `self.assertRedirects(response, 'http://testserver/some-url/')` should be replaced by `self.assertRedirects(response, '/some-url/')` (unless the redirection specifically contained an absolute URL).

In the rare case that you need the old behavior (discovered with an ancient version of Apache with `mod_scgi` that interprets a relative redirect as an « internal redirect »), you can restore it by writing a custom middleware:

    class LocationHeaderFix(object):
        def process_response(self, request, response):
            if 'Location' in response:
                response['Location'] = request.build_absolute_uri(response['Location'])
            return response

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

La prise en charge de PostgreSQL 9.0 par le projet amont s’est terminée en septembre 2015. Par conséquent, Django 1.9 a défini la version 1.9 comme la version minimum de PostgreSQL officiellement prise en charge.

### Abandon de la prise en charge de Oracle 11.1

La prise en charge de Oracle 11.1 par le projet amont s’est terminée en août 2015. Par conséquent, Django 1.9 a défini la version 11.2 comme la version minimum de Oracle officiellement prise en charge.

### Comportement d’ajout en bloc de la méthode `add()` des gestionnaires de relation

Pour améliorer les performances, les méthodes `add()` des gestionnaires de relation créés par les champs `ForeignKey` et `GenericForeignKey` ont modifé leur comportement d’une série d’appels à `Model.save()` à un seul appel à `QuerySet.update()`. Cette modification implique que les signaux `pre_save` et `post_save` ne sont plus envoyés dans ces situations. Vous pouvez utiliser le paramètre nommé `bulk=False` pour revenir à l’ancien comportement.

### Suppression de `LoaderOrigin` et `StringOrigin` des gabarits

Dans les versions précédentes de Django, quand un moteur de gabarit était initialisé avec `debug=True`, une instance de `django.template.loader.LoaderOrigin` ou de `django.template.base.StringOrigin` était définie comme attribut d’origine sur l’objet gabarit. Ces classes ont été réunies dans `Origin` et l’attribut est maintenant toujours défini, indépendamment du réglage de débogage du moteur. Pour un niveau minimal de rétrocompatibilité, les anciens noms de classes seront conservés comme alias de la nouvelle classe `Origin` jusqu’à Django 2.0.

### Changements de la configuration de journalisation par défaut

To make it easier to write custom logging configurations, Django’s default logging configuration no longer defines `django.request` and `django.security` loggers. Instead, it defines a single `django` logger, filtered at the `INFO` level, with two handlers:

- `console`: filtered at the `INFO` level and only active if `DEBUG=True`.
- `mail_admins`: filtered at the `ERROR` level and only active if `DEBUG=False`.

Si vous ne surchargez pas la journalisation par défaut de Django, vous ne devriez constater que des changements minimes dans le comportement, mais vous pourriez voir certains nouveaux messages dans la console `runserver`, par exemple.

Si vous surchargez la journalisation par défaut de Django, vous devriez vérifier la manière dont votre configuration fusionne avec les nouveaux paramètres par défaut.

### Détails `HttpRequest` dans les rapports d’erreur

Il était redondant d’afficher les détails complets de la requête `HttpRequest` chaque fois qu’elle apparaissait comme variable de la pile d’appels dans la version HTML de la page de débogage et du courriel d’erreur. Ainsi, la requête HTTP est affichée dorénavant avec la même représentation standard que les autres variables (`repr(request)`). En conséquence, la méthode `ExceptionReporterFilter.get_request_repr()` et la fonction non documentée `django.http.build_request_repr()` ont été supprimées.

Les contenus de la version textuelle du courriel ont été modifiés pour fournir une trace d’appels de la même structure que dans le cas de requêtes AJAX. Les détails de la trace d’appels sont produits par la méthode `ExceptionReporter.get_traceback_text()`.

### Suppression des adaptateurs et convertisseurs globaux de fuseau horaire pour les objets date/heure

Django n’inscrit plus d’adaptateurs ou de convertisseurs globaux pour la gestion des informations de fuseau horaire pour les valeurs `datetime` envoyées à la base de données en tant que paramètres de requête ou lues à partir de la base de données pour des résultats de requête. Ce changement affecte les projets qui répondent à toutes les conditions suivantes :

- Le réglage `USE_TZ` contient `True`.
- La base de données est SQLite, MySQL, Oracle ou une autre base de données tierce qui ne prend pas en charge les fuseaux horaires. En cas de doute, vous pouvez vérifier la valeur de `connection.features.supports_timezones`.
- Le code interroge la base de données en dehors de l’ORM, typiquement avec `cursor.execute(sql, params)`.

Si vous passez des paramètres `datetime` avec fuseau horaire à de telles requêtes, vous devriez les transformer en dates/heures naïves en UTC :

    from django.utils import timezone
    param = timezone.make_naive(param, timezone.utc)

Si vous ne le faites pas, la conversion sera effectuée comme dans les versions précédentes (avec un avertissement d’obsolescence) jusqu’à Django 1.11. Django 2.0 n’effectuera plus de conversion, ce qui pourrait aboutir à des corruptions de données.

Si vous lisez des valeurs `datetime` dans les résultats, elles seront naïves au lieu d’être conscientes. Vous pouvez compenser comme ceci :

    from django.utils import timezone
    value = timezone.make_aware(value, timezone.utc)

Tout ceci n’est pas nécessaire si vous interrogez la base de données au travers de l’ORM, même si vous utilisez des requêtes `raw()`. L’ORM se charge de gérer les informations de fuseau horaire.

### Les modules de balises de gabarit sont importés au moment où les gabarits sont configurés

Le moteur `DjangoTemplates` procède dorénavant à la découverte de modules de balises de gabarit installés lors de son instanciation. Ce changement permet d’activer explicitement des bibliothèques par la clé `'libraries'` de `OPTIONS` dans la définition d’un moteur `DjangoTemplates`. D’éventuelles erreurs d’importation ou de syntaxe dans les modules de balises de gabarit aboutissent à un échec rapide au moment de l’instanciation, plutôt qu’au moment de la première compilation d’un gabarit avec une balise `{% load %}`.

### Suppression de `django.template.base.add_to_builtins()`

Même s’il s’agissait d’une API privée, les projets utilisaient souvent `add_to_builtins()` pour rendre disponibles les balises et filtres de gabarit sans devoir utiliser la balise `{% load %}`. Cette API a été formalisée. Les projets doivent dorénavant intégrer les bibliothèques au moyen de la clé `'builtins'` de `OPTIONS` lors de la définition d’un moteur `DjangoTemplates`.

### Le résultat de `simple_tag` passe maintenant toujours par `conditional_escape`

In general, template tags do not autoescape their contents, and this behavior is documented. For tags like `inclusion_tag`, this is not a problem because the included template will perform autoescaping. For `assignment_tag()`, the output will be escaped when it is used as a variable in the template.

Cependant, pour les cas d’utilisation prévus pour `simple_tag`, il est très facile de se retrouver avec du code HTML incorrect et par conséquent avec un risque de faille XSS. Par exemple :

    @register.simple_tag(takes_context=True)
    def greeting(context):
        return "Hello {0}!".format(context['request'].user.first_name)

Dans les versions précédentes de Django, ceci est considéré comme une faille XSS car `user.first_name` n’est pas échappé.

Dans Django 1.9, c’est corrigé : si le contexte du gabarit possède `autoescape=True` (par défaut), `simple_tag` fera passer le résultat de la fonction de la balise par `conditional_escape()`.

Pour corriger vos balises `simple_tag`, voici les bonnes pratiques à appliquer :

- Tout code produisant du HTML devrait soit utiliser le système des gabarits, soit `format_html()`.
- Si le résultat d’une balise `simple_tag` a besoin d’être échappé, utilisez `escape()` ou `conditional_escape()`.
- Si vous êtes absolument certain que vous produisez du code HTML provenant d’une source fiable (par ex. un champ de CMS qui stocke du HTML saisi par des administrateurs), vous pouvez le signaler comme tel en utilisant `mark_safe()`.

Les balises qui suivent ces règles seront correctes et sûres, qu’elles fonctionnent avec Django 1.9+ ou des versions plus anciennes.

### `Paginator.page_range`

`Paginator.page_range` est dorénavant un itérateur au lieu d’une liste.

Dans les versions de Django avant 1.8, `Paginator.page_range` renvoyait un objet `list` en Python 2 et un objet `range` en Python 3. Django 1.8 renvoie toujours une liste, mais un itérateur est plus efficace.

Le code existant qui dépend des fonctionnalités spécifiques des objets `list`, comme l’indiçage, peut se charger de transformer l’itérateur en `list` avec la fonction `list()`.

### Interrogation implicite `__in` des `QuerySet` supprimée

Dans les versions précédentes, des requêtes telles que :

    Model.objects.filter(related_id=RelatedModel.objects.all())

étaient implicitement converties en :

    Model.objects.filter(related_id__in=RelatedModel.objects.all())

ce qui produisait du code SQL du style `"related_id IN (SELECT id FROM ...)"`.

L’opération `__in` implicite n’est plus effectuée, ce qui fait que le « IN » SQL est maintenant « = », et si la sous-requête renvoie plusieurs résultats, la plupart des bases de données vont générer une erreur.

### Navigateurs pris en charge par `contrib.admin`

Le site d’administration ne prend plus en charge les versions d’Internet Explorer 8 et plus anciennes, dans la mesure où ces navigateurs ont atteint leur fin de vie officielle.

Les images et le style CSS qui prenait en charge Internet Explorer 6 et 7 ont été supprimés. Les icônes PNG et GIF ont été remplacées par des icônes SVG qui ne sont pas prises en charge par Internet Explorer 8 ou les versions plus anciennes.

The jQuery library embedded in the admin has been upgraded from version 1.11.2 to 2.1.4. jQuery 2.x has the same API as jQuery 1.x, but does not support Internet Explorer 6, 7, or 8, allowing for better performance and a smaller file size. If you need to support IE8 and must also use the latest version of Django, you can override the admin’s copy of jQuery with your own by creating a Django application with this structure:

    app/static/admin/js/vendor/
        jquery.js
        jquery.min.js

### `SyntaxError` when installing Django setuptools 5.5.x

When installing Django 1.9 or 1.9.1 with setuptools 5.5.x, you’ll see:

    Compiling django/conf/app_template/apps.py ...
      File "django/conf/app_template/apps.py", line 4
        class {{ camel_case_app_name }}Config(AppConfig):
              ^
    SyntaxError: invalid syntax

    Compiling django/conf/app_template/models.py ...
      File "django/conf/app_template/models.py", line 1
        {{ unicode_literals }}from django.db import models
                                 ^
    SyntaxError: invalid syntax

It’s safe to ignore these errors (Django will still install just fine), but you can avoid them by upgrading setuptools to a more recent version. If you’re using pip, you can upgrade pip using `python -m pip install -U pip` which will also upgrade setuptools. This is resolved in later versions of Django as described in the Notes de publication de Django 1.9.2.

### Divers

- The jQuery static files in `contrib.admin` have been moved into a `vendor/jquery` subdirectory.
- The text displayed for null columns in the admin changelist `list_display` cells has changed from `(None)` (or its translated equivalent) to `-` (a dash).
- `django.http.responses.REASON_PHRASES` and `django.core.handlers.wsgi.STATUS_CODE_TEXT` have been removed. Use Python’s stdlib instead: `http.client.responses` for Python 3 and httplib.responses for Python 2.
- `ValuesQuerySet` and `ValuesListQuerySet` have been removed.
- The `admin/base.html` template no longer sets `window.__admin_media_prefix__` or `window.__admin_utc_offset__`. Image references in JavaScript that used that value to construct absolute URLs have been moved to CSS for easier customization. The UTC offset is stored on a data attribute of the `<body>` tag.
- `CommaSeparatedIntegerField` validation has been refined to forbid values like `','`, `',1'`, and `'1,,2'`.
- Form initialization was moved from the `ProcessFormView.get()` method to the new `FormMixin.get_context_data()` method. This may be backwards incompatible if you have overridden the `get_context_data()` method without calling `super()`.
- La prise en charge de PostGIS 1.5 a été abandonnée.
- Le champ `django.contrib.sites.models.Site.domain` a été défini comme `unique`.
- In order to enforce test isolation, database queries are not allowed by default in `SimpleTestCase` tests anymore. You can disable this behavior by setting the `allow_database_queries` class attribute to `True` on your test class.
- `ResolverMatch.app_name` was changed to contain the full namespace path in the case of nested namespaces. For consistency with `ResolverMatch.namespace`, the empty value is now an empty string instead of `None`.
- For security hardening, session keys must be at least 8 characters.
- Private function `django.utils.functional.total_ordering()` has been removed. It contained a workaround for a `functools.total_ordering()` bug in Python versions older than 2.7.3.
- XML serialization (either through `dumpdata` or the syndication framework) used to output any characters it received. Now if the content to be serialized contains any control characters not allowed in the XML 1.0 standard, the serialization will fail with a `ValueError`.
- `CharField` now strips input of leading and trailing whitespace by default. This can be disabled by setting the new `strip` argument to `False`.
- Template text that is translated and uses two or more consecutive percent signs, e.g. `"%%"`, may have a new `msgid` after `makemessages` is run (most likely the translation will be marked fuzzy). The new `msgid` will be marked `"#, python-format"`.
- If neither `request.current_app` nor `Context.current_app` are set, the `url` template tag will now use the namespace of the current request. Set `request.current_app` to `None` if you don’t want to use a namespace hint.
- The `SILENCED_SYSTEM_CHECKS` setting now silences messages of all levels. Previously, messages of `ERROR` level or higher were printed to the console.
- The `FlatPage.enable_comments` field is removed from the `FlatPageAdmin` as it’s unused by the application. If your project or a third-party app makes use of it, create a custom ModelAdmin to add it back.
- The return value of `setup_databases()` and the first argument of `teardown_databases()` changed. They used to be `(old_names, mirrors)` tuples. Now they’re just the first item, `old_names`.
- By default `LiveServerTestCase` attempts to find an available port in the 8081-8179 range instead of just trying port 8081.
- Les contrôles système pour `ModelAdmin` vérifient maintenant les instances plutôt que les classes.
- The private API to apply mixed migration plans has been dropped for performance reasons. Mixed plans consist of a list of migrations where some are being applied and others are being unapplied.
- The related model object descriptor classes in `django.db.models.fields.related` (private API) are moved from the `related` module to `related_descriptors` and renamed as follows:
  - `ReverseSingleRelatedObjectDescriptor` is `ForwardManyToOneDescriptor`
  - `SingleRelatedObjectDescriptor` is `ReverseOneToOneDescriptor`
  - `ForeignRelatedObjectsDescriptor` is `ReverseManyToOneDescriptor`
  - `ManyRelatedObjectsDescriptor` is `ManyToManyDescriptor`
- If you implement a custom `handler404` view, it must return a response with an HTTP 404 status code. Use `HttpResponseNotFound` or pass `status=404` to the `HttpResponse`. Otherwise, `APPEND_SLASH` won’t work correctly with `DEBUG=False`.

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

### `assignment_tag()`

Django 1.4 added the `assignment_tag` helper to ease the creation of template tags that store results in a template variable. The `simple_tag()` helper has gained this same ability, making the `assignment_tag` obsolete. Tags that use `assignment_tag` should be updated to use `simple_tag`.

### `{% cycle %}` syntax with comma-separated arguments

The `cycle` tag supports an inferior old syntax from previous Django versions:

    {% cycle row1,row2,row3 %}

Its parsing caused bugs with the current syntax, so support for the old syntax will be removed in Django 1.10 following an accelerated deprecation.

### `ForeignKey` and `OneToOneField` `on_delete` argument

In order to increase awareness about cascading model deletion, the `on_delete` argument of `ForeignKey` and `OneToOneField` will be required in Django 2.0.

Update models and existing migrations to explicitly set the argument. Since the default is `models.CASCADE`, add `on_delete=models.CASCADE` to all `ForeignKey` and `OneToOneField`s that don’t use a different option. You can also pass it as the second positional argument if you don’t care about compatibility with older versions of Django.

### `Field.rel` changes

`Field.rel` and its methods and attributes have changed to match the related fields API. The `Field.rel` attribute is renamed to `remote_field` and many of its methods and attributes are either changed or renamed.

The aim of these changes is to provide a documented API for relation fields.

### `GeoManager` and `GeoQuerySet` custom methods

All custom `GeoQuerySet` methods (`area()`, `distance()`, `gml()`, …) have been replaced by equivalent geographic expressions in annotations (see in new features). Hence the need to set a custom `GeoManager` to GIS-enabled models is now obsolete. As soon as your code doesn’t call any of the deprecated methods, you can simply remove the `objects = GeoManager()` lines from your models.

### Template loader APIs have changed

Django template loaders have been updated to allow recursive template extending. This change necessitated a new template loader API. The old `load_template()` and `load_template_sources()` methods are now deprecated. Details about the new API can be found in the template loader documentation.

### Passing a 3-tuple or an `app_name` to `include()`

The instance namespace part of passing a tuple as an argument to `include()` has been replaced by passing the `namespace` argument to `include()`. For example:

    polls_patterns = [
         url(...),
    ]

    urlpatterns = [
        url(r'^polls/', include((polls_patterns, 'polls', 'author-polls'))),
    ]

devient :

    polls_patterns = ([
         url(...),
    ], 'polls')  # 'polls' is the app_name

    urlpatterns = [
        url(r'^polls/', include(polls_patterns, namespace='author-polls')),
    ]

The `app_name` argument to `include()` has been replaced by passing a 2-tuple (as above), or passing an object or module with an `app_name` attribute (as below). If the `app_name` is set in this new way, the `namespace` argument is no longer required. It will default to the value of `app_name`. For example, the URL patterns in the tutorial are changed from:

monsite/urls.py

    urlpatterns = [
        url(r'^polls/', include('polls.urls', namespace="polls")),
        ...
    ]

to:

monsite/urls.py

    urlpatterns = [
        url(r'^polls/', include('polls.urls')),  # 'namespace="polls"' removed
        ...
    ]

polls/urls.py

    app_name = 'polls'  # added
    urlpatterns = [...]

This change also means that the old way of including an `AdminSite` instance is deprecated. Instead, pass `admin.site.urls` directly to `django.conf.urls.url()`:

urls.py

    from django.conf.urls import url
    from django.contrib import admin

    urlpatterns = [
        url(r'^admin/', admin.site.urls),
    ]

### URL application namespace required if setting an instance namespace

In the past, an instance namespace without an application namespace would serve the same purpose as the application namespace, but it was impossible to reverse the patterns if there was an application namespace with the same name. Includes that specify an instance namespace require that the included URLconf sets an application namespace.

### `current_app` parameter to `contrib.auth` views

All views in `django.contrib.auth.views` have the following structure:

    def view(request, ..., current_app=None, ...):

        ...

        if current_app is not None:
            request.current_app = current_app

        return TemplateResponse(request, template_name, context)

As of Django 1.8, `current_app` is set on the `request` object. For consistency, these views will require the caller to set `current_app` on the `request` instead of passing it in a separate argument.

### `django.contrib.gis.geoip`

The `django.contrib.gis.geoip2` module supersedes `django.contrib.gis.geoip`. The new module provides a similar API except that it doesn’t provide the legacy GeoIP-Python API compatibility methods.

### Divers

- The `weak` argument to `django.dispatch.signals.Signal.disconnect()` has been deprecated as it has no effect.
- The `check_aggregate_support()` method of `django.db.backends.base.BaseDatabaseOperations` has been deprecated and will be removed in Django 2.0. The more general `check_expression_support()` should be used instead.
- `django.forms.extras` is deprecated. You can find `SelectDateWidget` in `django.forms.widgets` (or simply `django.forms`) instead.
- Private API `django.db.models.fields.add_lazy_relation()` is deprecated.
- The `django.contrib.auth.tests.utils.skipIfCustomUser()` decorator is deprecated. With the test discovery changes in Django 1.6, the tests for `django.contrib` apps are no longer run as part of the user’s project. Therefore, the `@skipIfCustomUser` decorator is no longer needed to decorate tests in `django.contrib.auth`.
- If you customized some error handlers, the view signatures with only one request parameter are deprecated. The views should now also accept a second `exception` positional parameter.
- The `django.utils.feedgenerator.Atom1Feed.mime_type` and `django.utils.feedgenerator.RssFeed.mime_type` attributes are deprecated in favor of `content_type`.
- `Signer` now issues a warning if an invalid separator is used. This will become an exception in Django 1.10.
- `django.db.models.Field._get_val_from_obj()` is deprecated in favor of `Field.value_from_object()`.
- `django.template.loaders.eggs.Loader` is deprecated as distributing applications as eggs is not recommended.
- The `callable_obj` keyword argument to `SimpleTestCase.assertRaisesMessage()` is deprecated. Pass the callable as a positional argument instead.
- The `allow_tags` attribute on methods of `ModelAdmin` has been deprecated. Use `format_html()`, `format_html_join()`, or `mark_safe()` when constructing the method’s return value instead.
- The `enclosure` keyword argument to `SyndicationFeed.add_item()` is deprecated. Use the new `enclosures` argument which accepts a list of `Enclosure` objects instead of a single one.
- The `django.template.loader.LoaderOrigin` and `django.template.base.StringOrigin` aliases for `django.template.base.Origin` are deprecated.

## Features removed in 1.9

These features have reached the end of their deprecation cycle and are removed in Django 1.9. See Fonctionnalités déconseillées dans 1.7 for details, including how to remove usage of these features.

- `django.utils.dictconfig` is removed.
- `django.utils.importlib` is removed.
- `django.utils.tzinfo` is removed.
- `django.utils.unittest` is removed.
- The `syncdb` command is removed.
- `django.db.models.signals.pre_syncdb` and `django.db.models.signals.post_syncdb` is removed.
- Support for `allow_syncdb` on database routers is removed.
- Automatic syncing of apps without migrations is removed. Migrations are compulsory for all apps unless you pass the `migrate --run-syncdb` option.
- The SQL management commands for apps without migrations, `sql`, `sqlall`, `sqlclear`, `sqldropindexes`, and `sqlindexes`, are removed.
- Support for automatic loading of `initial_data` fixtures and initial SQL data is removed.
- All models need to be defined inside an installed application or declare an explicit `app_label`. Furthermore, it isn’t possible to import them before their application is loaded. In particular, it isn’t possible to import models inside the root package of an application.
- The model and form `IPAddressField` is removed. A stub field remains for compatibility with historical migrations.
- `AppCommand.handle_app()` is no longer supported.
- `RequestSite` and `get_current_site()` are no longer importable from `django.contrib.sites.models`.
- FastCGI support via the `runfcgi` management command is removed.
- `django.utils.datastructures.SortedDict` is removed.
- `ModelAdmin.declared_fieldsets` is removed.
- The `util` modules that provided backwards compatibility are removed:
  - `django.contrib.admin.util`
  - `django.contrib.gis.db.backends.util`
  - `django.db.backends.util`
  - `django.forms.util`
- `ModelAdmin.get_formsets` is removed.
- The backward compatible shims introduced to rename the `BaseMemcachedCache._get_memcache_timeout()` method to `get_backend_timeout()` is removed.
- The `--natural` and `-n` options for `dumpdata` are removed.
- The `use_natural_keys` argument for `serializers.serialize()` is removed.
- Private API `django.forms.forms.get_declared_fields()` is removed.
- The ability to use a `SplitDateTimeWidget` with `DateTimeField` is removed.
- The `WSGIRequest.REQUEST` property is removed.
- The class `django.utils.datastructures.MergeDict` is removed.
- The `zh-cn` and `zh-tw` language codes are removed.
- The internal `django.utils.functional.memoize()` is removed.
- `django.core.cache.get_cache` is removed.
- `django.db.models.loading` a été supprimé.
- Passing callable arguments to querysets is no longer possible.
- `BaseCommand.requires_model_validation` is removed in favor of `requires_system_checks`. Admin validators is replaced by admin checks.
- The `ModelAdmin.validator_class` and `default_validator_class` attributes are removed.
- `ModelAdmin.validate()` is removed.
- `django.db.backends.DatabaseValidation.validate_field` is removed in favor of the `check_field` method.
- The `validate` management command is removed.
- `django.utils.module_loading.import_by_path` is removed in favor of `django.utils.module_loading.import_string`.
- `ssi` and `url` template tags are removed from the `future` template tag library.
- `django.utils.text.javascript_quote()` is removed.
- Database test settings as independent entries in the database settings, prefixed by `TEST_`, are no longer supported.
- The `cache_choices` option to `ModelChoiceField` and `ModelMultipleChoiceField` is removed.
- The default value of the `RedirectView.permanent` attribute has changed from `True` to `False`.
- `django.contrib.sitemaps.FlatPageSitemap` is removed in favor of `django.contrib.flatpages.sitemaps.FlatPageSitemap`.
- L’API privée `django.test.utils.TestTemplateLoader` a été supprimée.
- Le module `django.contrib.contenttypes.generic` a été supprimé.