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.

This functionality from the django-transaction-hooks package has been integrated into 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

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

django.contrib.sessions

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

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 now calls xgettext once per locale directory rather than once per translatable file. This speeds up localization builds.
  • 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.
  • The BrokenLinkEmailsMiddleware now ignores 404s when the referer is equal to the requested URL. To circumvent the empty referer check already implemented, some web bots set the referer to the requested URL.

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

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é

Django template loaders previously required an is_usable attribute to be defined. If a loader was configured in the template settings and this attribute was False, the loader would be silently ignored. In practice, this was only used by the egg loader to detect if setuptools was installed. The is_usable attribute is now removed and the egg loader instead fails at runtime if setuptools is not installed.

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.

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 Standard Library 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 OneToOneFields 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é.
Back to Top