Notes de publication de Django 3.0¶
2 décembre 2019
Bienvenue dans Django 3.0 !
Ces notes de publications couvrent les nouvelles fonctionnalités, ainsi que certaines modifications non rétro-compatibles dont il faut être au courant lors la mise à jour depuis Django 2.2 ou des versions plus anciennes. Nous avons abandonné certaines fonctionnalités qui ont atteint la fin de leur cycle d’obsolescence et nous avons commencé le processus d’obsolescence de certaines fonctionnalités.
Voir le guide Mise à jour de Django à une version plus récente si vous mettez à jour un projet existant.
Compatibilité Python¶
Django 3.0 requiert Python 3.6, 3.7, 3.8 ou 3.9 (dès 3.0.11). Nous recommandons vivement et nous ne prenons officiellement en charge que la dernière publication de chaque série.
La série Django 2.2.x est la dernière à prendre en charge Python 3.5.
Prise en charge des bibliothèques tierces pour les anciennes versions de Django¶
Après la publication de Django 3.0, nous suggérons aux applications tierces de ne plus prendre en charge les versions de Django plus anciennes que 2.2. À ce moment, vous devriez pouvoir exécuter les tests de votre projet en utilisant python -Wd afin de faire apparaître les avertissements d’obsolescence. Après avoir corrigé ceux-ci, votre application devrait être compatible avec Django 3.0.
Quoi de neuf dans Django 3.0¶
Prise en charge de MariaDB¶
Django prend dorénavant officiellement en charge MariaDB 10.1 ou plus récent. Lisez les notes MariaDB pour plus de détails.
Prise en charge d’ASGI¶
Django 3.0 commence le voyage vers la fonctionnalité asynchrone de Django en fournissant la prise en charge de l’exécution d’applications ASGI.
Il s’agit d’un ajout en plus de la prise en charge existante du protocole WSGI. Django prévoit de prendre en charge les deux à l’avenir. Les fonctionnalités asychrones ne seront toutefois disponibles que pour les applications fonctionnant avec ASGI.
At this stage async support only applies to the outer ASGI application. Internally everything remains synchronous. Asynchronous middleware, views, etc. are not yet supported. You can, however, use ASGI middleware around Django’s application, allowing you to combine Django with other ASGI frameworks.
Aucun besoin de convertir vos applications sauf si vous souhaitez expérimenter avec du code asynchrone ; si vous souhaitez en savoir plus, vous pouvez lire la documentation sur le déploiement avec ASGI.
Notez qu’un effet de bord de cette nouveauté est que Django sait maintenant détecter des boucles événementielles asynchrones et vous empêchera d’appeler du code marqué comme non adapté à l’asynchrone (« async unsafe »), tel que des opérations avec l’ORM, à partir d’un contexte asynchrone. Si vous utilisiez précédemment Django à partir de code asynchrone, ceci pourrait vous bloquer si vous ne le faisiez pas correctement. Si vous voyez une erreur SynchronousOnlyOperation
, examinez attentivement votre code et déplacez d’éventuelles opérations de base de données plutôt dans un fil d’exécution synchrone.
Contraintes d’exclusion avec PostgreSQL¶
La nouvelle classe ExclusionConstraint
permet d’ajouter des contraintes d’exclusion avec PostgreSQL Ces contraintes peuvent être ajoutées aux modèles en utilisant l’option Meta.constraints
.
Expressions de filtres¶
Les expressions qui produisent des résultats BooleanField
peuvent dorénavant être directement utilisées dans des filtres QuerySet
, sans devoir passer par une annotation préalable et un filtre sur cette annotation.
Énumérations pour les choix de champs de modèles¶
Les types d’énumération personnalisés TextChoices
, IntegerChoices
et Choices
sont dorénavant disponibles dans l’optique de définir Field.choices
. Les types TextChoices
et IntegerChoices
sont fournis pour les champs texte et nombre entier. La classe Choices
permet de définir une énumération compatible avec les autres types de données concrets. Ces types personnalisés prennent en charge les étiquettes conviviales pouvant être traduites et obtenues par une propriété de l’énumération ou de ses membres. Lisez Types énumératifs pour plus de détails et des exemples.
Fonctionnalités mineures¶
django.contrib.admin
¶
- La prise en charge de l’attribut
admin_order_field
pour les propriétés dansModelAdmin.list_display
. - La nouvelle méthode
ModelAdmin.get_inlines()
permet de définir les sous-formulaires intégrés sur la base de la requête ou de l’instance de modèle. - La bibliothèque Select2 a été mise à jour de la version 4.0.3 vers 4.0.7.
- La version intégrée de jQuery a été mise à jour de 3.3.1 vers 3.4.1.
django.contrib.auth
¶
- Le nouvel attribut
reset_url_token
dansPasswordResetConfirmView
permet de définir un paramètre jeton affiché comme composant des URL de réinitialisation de mot de passe. - La classe
BaseBackend
a été ajoutée pour faciliter la personnalisation des moteurs d’authentification. - La méthode
get_user_permissions()
a été ajoutée pour faire écho à la méthode existanteget_group_permissions()
. - L’attribut HTML
autocomplete
a été ajouté aux composants des champs nom d’utilisateur, courriel et mot de passe dansdjango.contrib.auth.forms
pour une meilleure interaction avec les gestionnaires de mots de passe des navigateurs. createsuperuser
se replie sur les variables d’environnement pour les champs mot de passe et autres champs obligatoires, lorsqu’elle ne trouve pas de paramètre correspondant sur la ligne de commande en mode non interactif.REQUIRED_FIELDS
prend dorénavant en charge les champsManyToManyField
.- La nouvelle méthode
UserManager.with_perm()
renvoie les utilisateurs ayant la permission indiquée. - Le nombre d’itération par défaut du hacheur de mot de passe PBKDF2 a été augmenté de 150’000 à 180’000.
django.contrib.gis
¶
- Les fonctions de requête spatiale MySQL opèrent dorénavant sur les géométries réelles. Précédemment, seules les boîtes englobantes étaient prises en compte.
- La fonction
GeometryDistance
a été ajoutée, prise en charge par PostGIS. - La prise en charge de l’unité
furlong
(sillon) a été ajoutée dansDistance
. - Le réglage
GEOIP_PATH
accepte maintenant les cheminspathlib.Path
. - La classe
GeoIP2
accepte maintenant les cheminspathlib.Path
.
django.contrib.postgres
¶
- La nouvelle classe
RangeOperators
aide à éviter les erreurs de syntaxe dans les opérateurs SQL qui peuvent être utilisés conjointement avecRangeField
. - La nouvelle expression
RangeBoundary
représente les limites des intervalles. - Les nouvelles classes
AddIndexConcurrently
etRemoveIndexConcurrently
permettent de créer et de supprimer des index de manière concurrente avec PostgreSQL.
django.contrib.sessions
¶
- La nouvelle méthode
get_session_cookie_age()
permet de définir dynmaiquement l’âge du cookie de session.
django.contrib.syndication
¶
- Un attribut de classe
language
a été ajouté àdjango.contrib.syndication.views.Feed
pour pouvoir personnaliser la langue d’un flux. La valeur par défaut estget_language()
au lieu deLANGUAGE_CODE
.
Cache¶
add_never_cache_headers()
etnever_cache()
ajoutent dorénavant la directiveprivate
aux en-têtesCache-Control
.
Stockage de fichier¶
- La nouvelle méthode
Storage.get_alternative_name()
permet d’adapter l’algorithme de génération des noms de fichiers lorsque le nom d’un fichier téléversé existe déjà.
Formulaires¶
- Les jeux de formulaires peuvent contrôler le composant utilisé pour le tri des formulaires avec
can_order
en définissant l’attributordering_widget
ou en surchargeantget_ordering_widget()
.
Internationalisation¶
- Les réglages
LANGUAGE_COOKIE_HTTPONLY
,LANGUAGE_COOKIE_SAMESITE
etLANGUAGE_COOKIE_SECURE
ont été ajoutés pour définir les drapeauxHttpOnly
,SameSite
etSecure
sur les cookies de langue. Les valeurs par défaut de ces réglages préservent le comportement historique. - La prise en charge des traductions en ouzbek a été ajoutée.
Journalisation¶
- Le nouveau paramètre
reporter_class
deAdminEmailHandler
permet de fournir une sous-classe dedjango.views.debug.ExceptionReporter
pour personnaliser le texte de trace d’erreur envoyé auxADMINS
du site lorsqueDEBUG
vautFalse
.
Commandes d’administration¶
- La nouvelle option
compilemessages --ignore
permet d’ignorer des répertoires spécifiques lors de la recherche de fichiers.po
à compiler. showmigrations --list
affiche dorénavant la date d’application lorsque--verbosity
est de 2 ou plus.- Avec PostgreSQL,
dbshell
prend dorénavant en charge les certificats TLS client. inspectdb
sait dorénavant découvrir les champsOneToOneField
lorsqu’une clé étrangère possède une contrainte unique ou de clé primaire.- La nouvelle option
--skip-checks
omet l’exécution des contrôles système avant de lancer la commande. - Les options
startapp --template
etstartproject --template
prennent maintenant en charge les gabarits stockés dans des archives XZ (.tar.xz
,.txz
) et LZMA (.tar.lzma
,.tlz
).
Modèles¶
Les fonctions de base de données de génération d’empreintes
MD5
,SHA1
,SHA224
,SHA256
,SHA384
etSHA512
ont été ajoutées.La fonction de base de données
Sign
a été ajoutée.Le nouveau paramètre
is_dst
des fonctions de base de donnéesTrunc
détermine le traitement des heures non existantes ou ambiguës.connection.queries
affiche dorénavant les instructionsCOPY … TO
avec PostgreSQL.FilePathField
accepte dorénavant un objet exécutable pourpath
.Les tables intermédiaires symétriques sont permises pour les champs auto-référencés
ManyToManyField
.Les attributs
name
deCheckConstraint
,UniqueConstraint
etIndex
prennent dorénavant en charge l’interpolation de classe et d’étiquette d’application en utilisant les substituants'%(app_label)s'
et'%(class)s'
.Le nouvel attribut
Field.descriptor_class
permet aux champs de modèles de personnaliser le comportement get et set en surchargeant leurs descripteurs.Le champ
SmallAutoField
a été ajouté ; il est similaire àAutoField
sauf qu’il ne permet des valeurs que jusqu’à une certaine limite (dépendante de la base de données). Les valeurs de1
à32767
sont valables pour toutes les bases de données prises en charge par Django.AutoField
,BigAutoField
etSmallAutoField
héritent dorénavant respectivement deIntegerField
,BigIntegerField
etSmallIntegerField
. Les contrôles système et les validateurs sont aussi correctement hérités.FileField.upload_to
accepte maintenant les cheminspathlib.Path
.CheckConstraint
est dorénavant prise en charge avec MySQL 8.0.16+.La nouvelle méthode
allows_group_by_selected_pks_on_model()
dedjango.db.backends.base.BaseDatabaseFeatures
permet d’optimiser les clausesGROUP BY
pour n’exiger que les clés primaires des modèles sélectionnés. Par défaut, elle n’est prise en charge que pour les modèles gérés avec PostgreSQL.Pour activer l’optimisation de clé primaire seule pour
GROUP BY
pour les modèles non gérés (« unmanaged »), vous deez créer une sous-classe du moteur de base de données PostgreSQL, surchargeant la classe de fonctionnalitéfeatures
avec une méthodeallows_group_by_selected_pks_on_model()
selon vos besoins. Voir l’exemple Sous-classes des moteurs de base de données intégrés.
Requêtes et réponses¶
HttpResponse
peut maintenant être initialisée avec du contenumemoryview
.- For use in, for example, Django templates,
HttpRequest.headers
now allows lookups using underscores (e.g.user_agent
) in place of hyphens.
Sécurité¶
- La valeur par défaut de
X_FRAME_OPTIONS
est dorénavant'DENY'
. Dans les anciennes versions, cette valeur par défaut était'SAMEORIGIN'
. Si votre site utilise des cadres (« frames ») de lui-même, vous devrez explicitement définirX_FRAME_OPTIONS = 'SAMEORIGIN'
pour qu’ils continuent à fonctionner. SECURE_CONTENT_TYPE_NOSNIFF
now defaults toTrue
. With this enabled,SecurityMiddleware
sets the X-Content-Type-Options: nosniff header on all responses that do not already have it.SecurityMiddleware
peut dorénavant envoyer l’en-tête Referrer-Policy.
Tests¶
- Le nouveau paramètre
raise_request_exception
de la classe de testClient
permet de contrôler si les exceptions générées pendant la requête doivent être propagées dans les tests. La valeur par défaut estTrue
pour des raisons de rétrocompatibilité. Quand elle vautFalse
et qu’une exception survient, le client de test renverra une réponse 500 avec l’attributexc_info
, un tuple fournissant des informations sur l’exception survenue. - Les tests et les cas de tests à lancer peuvent être choisis par un motif de nom de test à l’aide de la nouvelle option
test -k
. - La comparaison HTML, telle qu’utilisée par
assertHTMLEqual()
traite dorénavant le texte, les références de caractères et les références d’entité qui se réfèrent au même caractère comme équivalents. - Le lanceur de tests de Django prend dorénavant en charge le mode sans interface pour les tests Selenium avec les navigateurs pris en charge. Ajoutez l’option
--headless
pour activer ce mode. - Le lanceur de tests de Django prend dorénavant en charge les options
--start-at
et--start-after
pour lancer les tests en commençant à partir d’un certain module de premier niveau. - Le lanceur de tests de Django prend dorénavant en charge une option
--pdb
pour déclencher un débogueur à chaque erreur ou échec.
Changements incompatibles avec les anciennes versions dans Django 3.0¶
Model.save()
when providing a default for the primary key¶
Model.save()
no longer attempts to find a row when saving a new
Model
instance and a default value for the primary key is provided, and
always performs a single INSERT
query. In older Django versions,
Model.save()
performed either an INSERT
or an UPDATE
based on
whether or not the row exists.
This makes calling Model.save()
while providing a default primary key value
equivalent to passing force_insert=True to
model’s save()
. Attempts to use a new Model
instance to update an
existing row will result in an IntegrityError
.
In order to update an existing model for a specific primary key value, use the
update_or_create()
method or
QuerySet.filter(pk=…).update(…)
instead. For example:
>>> MyModel.objects.update_or_create(pk=existing_pk, defaults={"name": "new name"})
>>> MyModel.objects.filter(pk=existing_pk).update(name="new name")
API de moteur de base de données¶
Cette section décrit des modifications qui pourraient être nécessaires dans des moteurs de base de données tiers.
- Le second paramètre de
DatabaseIntrospection.get_geometry_type()
est dorénavant la description de la ligne au lieu du nom de la colonne. DatabaseIntrospection.get_field_type()
ne renvoie plus forcément des tuples.- Si une base de données peut créer des clés étrangères dans la même instruction SQL qui ajoute un champ, ajoutez l’attribut
SchemaEditor.sql_create_column_inline_fk
à son moteur, avec le contenu SQL approprié ; sinon, définissezDatabaseFeatures.can_create_inline_fk = False
. DatabaseFeatures.can_return_id_from_insert
etcan_return_ids_from_bulk_insert
sont renommés encan_return_columns_from_insert
etcan_return_rows_from_bulk_insert
.- Les fonctions de base de données prennent maintenant en charge les formats
datetime.timezone
lorsqu’elles sont créées avec des instancesdatetime.timedelta
(par ex.timezone(timedelta(hours=5))
, qui produirait'UTC+05:00'
). Les moteurs tiers doivent prendre en compte ce format lors de la préparation deDateTimeField
dansdatetime_cast_date_sql()
,datetime_extract_sql()
, etc. - Des lignes sont ajoutées à
DatabaseOperations.integer_field_ranges
pour les champsAutoField
,BigAutoField
etSmallAutoField
afin de prendre en charge les validateurs d’intervalles de nombres entiers pour ces types de champ. Les moteurs tiers pourraient avoir à adapter les lignes par défaut. DatabaseOperations.fetch_returned_insert_id()
est remplacée parfetch_returned_insert_columns()
qui renvoie une liste de valeurs renvoyées par l’instructionINSERT … RETURNING
au lieu d’une valeur unique.DatabaseOperations.return_insert_id()
est remplacée parreturn_insert_columns()
qui accepte un paramètrefields
qui est un itérable de champs à renvoyer après l’insertion. Généralement, il ne s’agit que du champ clé primaire auto-généré.
django.contrib.admin
¶
- Les messages de changement des historiques de modèle du site d’administration préfèrent dorénavant les étiquettes de champ plus lisibles plutôt que les noms de champ.
django.contrib.gis
¶
- La prise en charge de PostGIS 2.1 a été supprimée.
- La prise en charge de SpatiaLite 4.1 et 4.2 a été supprimée.
- La prise en charge de GDAL 1.11 et GEOS 3.4 a été supprimée.
Abandon de la prise en charge de PostgreSQL 9.4¶
La prise en charge amont de PostgreSQL 9.4 se termine en décembre 2019. Django 3.0 prend en charge PostgreSQL 9.5 et plus récent.
Abandon de la prise en charge de Oracle 12.1¶
La prise en charge de Oracle 12.1 par le projet amont se termine en juillet 2021. Django 2.2 sera pris en charge jusqu’en avril 2022. Django 3.0 prend officiellement en charge Oracle 12.2 et 18c.
Les API de compatibilité privées de Python 2 ont été supprimées.¶
Bien que la prise en charge de Python 2 ait été supprimée dans Django 2.0, certaines API privées n’ont pas été supprimées de Django afin que des applications tierces puissent continuer à les utiliser jusqu’à la fin de vie de Python 2.
Comme nous nous attendons à ce que les applications abandonnent la compatibilité avec Python 2 lors de l’ajout de la prise en charge de Django 3.0, nous supprimons ces API dans cette version.
django.test.utils.str_prefix()
- Les chaînes n’ont plus de préfixe « u » avec Python 3.django.test.utils.patch_logger()
- Utilisezunittest.TestCase.assertLogs()
à la place.django.utils.lru_cache.lru_cache()
- Alias defunctools.lru_cache()
.django.utils.decorators.available_attrs()
- Cette fonction renvoiefunctools.WRAPPER_ASSIGNMENTS
.django.utils.decorators.ContextDecorator
- Alias decontextlib.ContextDecorator
.django.utils._os.abspathu()
- Alias deos.path.abspath()
.django.utils._os.upath()
etnpath()
- Ces fonctions ne font plus rien en Python 3.django.utils.six
- Remove usage of this vendored library or switch to six.django.utils.encoding.python_2_unicode_compatible()
- Alias desix.python_2_unicode_compatible()
.django.utils.functional.curry()
- Usefunctools.partial()
orfunctools.partialmethod
. See 5b1c389603a353625ae1603ba345147356336afb.django.utils.safestring.SafeBytes
- Inutilisée depuis Django 2.0.
Nouvelle valeur par défaut du réglage FILE_UPLOAD_PERMISSIONS
¶
Dans les versions précédentes, le réglage FILE_UPLOAD_PERMISSIONS
valait None
par défaut. Avec le gestionnaire par défaut FILE_UPLOAD_HANDLERS
, cela pouvait aboutir à des fichiers téléversés ayant des permissions différentes dépendant de leur taille et donc de quel gestionnaire de téléversement était utilisé.
FILE_UPLOAD_PERMISSIONS
now defaults to 0o644
to avoid this
inconsistency.
Nouvelles valeurs par défaut de réglages de sécurité¶
Pour rendre les projets Django plus sûrs par défaut, certains réglages de sécurité ont dorénavant des valeurs par défaut plus sûres :
- La nouvelle valeur par défaut de
X_FRAME_OPTIONS
est'DENY'
. - La nouvelle valeur par défaut de
SECURE_CONTENT_TYPE_NOSNIFF
estTrue
.
Consultez la section sécurité des nouveautés de Django 3.0 pour plus de détails sur ces changements.
Divers¶
ContentType.__str__()
inclut dorénavant l’étiquetteapp_label
de son modèle pour distinguer les modèles ayant le même nom dans des applications différentes.- Comme l’accès à la langue dans la session a été rendu obsolète au profit des cookies,
LocaleMiddleware
ne cherche plus la langue de l’utilisateur dans la session etdjango.contrib.auth.logout()
ne préserve plus la langue de la session après la déconnexion. django.utils.html.escape()
utilise dorénavanthtml.escape()
pour l’échappement du code HTML. Le guillemet simple'
est dorénavant converti en'
au lieu de l’équivalent en format décimal'
.- L’option
django-admin test -k
fonctionne dorénavant comme l’optionunittest -k
plutôt que comme un raccourci de--keepdb
. - La prise en charge de
pywatchman
< 1.2.0 a été abandonnée. urlencode()
code dorénavant les valeurs itérables telles qu’elles sont lorsquedoseq=False
, plutôt que de les passer en boucle, ce qui rapproche du comportement de la fonction de bibliothèque standardurllib.parse.urlencode()
.- Le filtre de gabarit
intword
traduit dorénavant1.0
avec une phrase au singulier et toutes les autres valeurs numériques comme une phrase au pluriel, ce qui n’est pas toujours correct selon les langues. - Assigning a value to a model’s
ForeignKey
orOneToOneField
'_id'
attribute now unsets the corresponding field. Accessing the field afterward will result in a query. patch_vary_headers()
traite dorénavant l’astérisque'*'
en accord avec la RFC 7231#section-7.1.4, c’est-à-dire que si une liste de noms de champs d’en-tête contient un astérisque, l’en-têteVary
sera formé d’un seul astérisque'*'
.- Avec MySQL 8.0.16+,
PositiveIntegerField
etPositiveSmallIntegerField
incluent dorénavant une contrainte de contrôle pour empêcher les valeurs négatives dans la base de données. alias=None
a été ajouté à la signature deExpression.get_group_by_cols()
.RegexPattern
, used byre_path()
, no longer returns keyword arguments withNone
values to be passed to the view for the optional named groups that are missing.
Fonctionnalités rendues obsolètes dans Django 3.0¶
django.utils.encoding.force_text()
et smart_text()
¶
Les alias smart_text()
et force_text()
(depuis Django 2.0) de smart_str()
et force_str()
sont rendus obsolètes. Vous pouvez ignorer l’avertissement si votre code prend en charge Python 2 car le comportement de smart_str()
et force_str()
est différent dans ce contexte.
Divers¶
django.utils.http.urlquote()
,urlquote_plus()
,urlunquote()
eturlunquote_plus()
sont rendus obsolètes en faveur des fonctions pour lesquelles elles sont des alias :urllib.parse.quote()
,quote_plus()
,unquote()
etunquote_plus()
.django.utils.translation.ugettext()
,ugettext_lazy()
,ugettext_noop()
,ungettext()
etungettext_lazy()
sont rendues obsolètes en faveur des fonctions pour lesquelles elles sont des alias :django.utils.translation.gettext()
,gettext_lazy()
,gettext_noop()
,ngettext()
etngettext_lazy()
.- Afin de limiter la création de sessions et donc de favorise certaines stratégies de cache,
django.views.i18n.set_language()
arrêtera de définir la langue de l’utilisateur dans la session à partir de Django 4.0. Dès Django 2.1, la langue est toujours stockée dans le cookieLANGUAGE_COOKIE_NAME
. django.utils.text.unescape_entities()
est rendu obsolète en faveur dehtml.unescape()
. Notez qu’au contraire deunescape_entities()
,html.unescape()
évalue immédiatement les chaînes différées.- Pour éviter une possible confusion sur sa portée réelle, l’utilitaire interne privé
is_safe_url()
a été renommé enurl_has_allowed_host_and_scheme()
. Le fait que le protocole et l’hôte d’une URL soit autorisés n’implique en général pas qu’elle soit sûre. Elle pourrait par exemple être codée de façon incorrecte. Assurez-vous d’appliquer aussiiri_to_uri()
sur la partie chemin des URL de source non fiable.
Fonctionnalités supprimées dans 3.0¶
Ces fonctionnalités ont atteint la fin de leur cycle d’obsolescence et sont supprimées dans Django 3.0.
Voir Features deprecated in 2.0 pour les détails de ces changements, ainsi que pour savoir comment supprimer l’utilisation de ces fonctionnalités.
- Le module
django.db.backends.postgresql_psycopg2
a été supprimé. django.shortcuts.render_to_response()
a été supprimée.- Le réglage
DEFAULT_CONTENT_TYPE
a été supprimé. HttpRequest.xreadlines()
a été supprimée.- La prise en charge du paramètre
context
deField.from_db_value()
et deExpression.convert_value()
a été supprimée. - Le paramètre nommé
field_name
deQuerySet.earliest()
et delatest()
a été supprimé.
Voir Fonctionnalités rendues obsolètes dans Django 2.1 pour les détails de ces changements, ainsi que pour savoir comment supprimer l’utilisation de ces fonctionnalités.
- La fonction SIG
ForceRHR
a été supprimée. django.utils.http.cookie_date()
a été supprimée.- Les bibliothèques de balises de gabarits
staticfiles
etadmin_static
ont été supprimées. django.contrib.staticfiles.templatetags.staticfiles.static()
a été supprimée.