Personnaliser le site d'administration de Django

DjangoDjangoBeginner
Pratiquer maintenant

💡 Ce tutoriel est traduit par l'IA à partir de la version anglaise. Pour voir la version originale, vous pouvez cliquer ici

Introduction

Ce tutoriel reprend là où Ajoutez une feuille de style et une image s'est arrêté. Nous continuons l'application de sondage web et nous allons nous concentrer sur la personnalisation du site d'administration automatiquement généré par Django que nous avons d'abord exploré dans Configurez la base de données.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL django(("Django")) -.-> django/DatabaseModelsandMigrationsGroup(["Database, Models, and Migrations"]) django(("Django")) -.-> django/UserInterfaceandInteractionGroup(["User Interface and Interaction"]) django(("Django")) -.-> django/DevelopmentandAdministrationToolsGroup(["Development and Administration Tools"]) django/DatabaseModelsandMigrationsGroup -.-> django/models("Models") django/DatabaseModelsandMigrationsGroup -.-> django/databases("Databases") django/DatabaseModelsandMigrationsGroup -.-> django/schemaeditor("SchemaEditor") django/UserInterfaceandInteractionGroup -.-> django/templates("Templates") django/DevelopmentandAdministrationToolsGroup -.-> django/django_admin("Django Admin") django/DevelopmentandAdministrationToolsGroup -.-> django/contrib_packages("Contrib Packages") subgraph Lab Skills django/models -.-> lab-153747{{"Personnaliser le site d'administration de Django"}} django/databases -.-> lab-153747{{"Personnaliser le site d'administration de Django"}} django/schemaeditor -.-> lab-153747{{"Personnaliser le site d'administration de Django"}} django/templates -.-> lab-153747{{"Personnaliser le site d'administration de Django"}} django/django_admin -.-> lab-153747{{"Personnaliser le site d'administration de Django"}} django/contrib_packages -.-> lab-153747{{"Personnaliser le site d'administration de Django"}} end

Personnaliser le formulaire d'administration

En enregistrant le modèle Question avec admin.site.register(Question), Django a été capable de construire une représentation de formulaire par défaut. Souvent, vous voudrez personnaliser l'apparence et le fonctionnement du formulaire d'administration. Vous le ferez en informant Django des options que vous souhaitez lorsque vous enregistrez l'objet.

Voyons comment cela fonctionne en réordonnant les champs du formulaire d'édition. Remplacez la ligne admin.site.register(Question) par :

Modifiez le fichier ~/project/mysite/polls/admin.py pour qu'il ressemble à ceci :

from django.contrib import admin

from.models import Question


class QuestionAdmin(admin.ModelAdmin):
    fields = ["pub_date", "question_text"]


admin.site.register(Question, QuestionAdmin)

Vous suivrez ce modèle - créer une classe d'administration de modèle, puis la passer en tant que deuxième argument à admin.site.register() - chaque fois que vous devrez changer les options d'administration pour un modèle.

Exécutez le serveur de développement Django :

cd ~/project/mysite
python manage.py runserver

Ouvrez http://127.0.0.1:8000/admin/ dans Firefox de l'environnement de bureau et cliquez sur le lien "Questions". Vous devriez voir un formulaire qui ressemble à ceci.

Ce changement particulier ci-dessus fait en sorte que la "Date de publication" soit avant le champ "Question" :

Admin form field reorder

Cela n'est pas impressionnant avec seulement deux champs, mais pour les formulaires d'administration avec des dizaines de champs, choisir un ordre intuitif est un détail d'ergonomie important.

Et parlant de formulaires avec des dizaines de champs, vous pouvez vouloir diviser le formulaire en groupes de champs :

from django.contrib import admin

from.models import Question


class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None, {"fields": ["question_text"]}),
        ("Informations de date", {"fields": ["pub_date"]}),
    ]


admin.site.register(Question, QuestionAdmin)

Le premier élément de chaque tuple dans ~django.contrib.admin.ModelAdmin.fieldsets est le titre du groupe de champs. Voici à quoi ressemble maintenant notre formulaire :

Admin form with fieldsets

Ajout d'objets liés

Tout va bien, nous avons notre page d'administration de Question, mais une Question a plusieurs Choice, et la page d'administration ne montre pas les choix.

Pour l'instant.

Il existe deux manières de résoudre ce problème. La première consiste à enregistrer Choice auprès de l'administrateur tout comme nous l'avons fait avec Question :

from django.contrib import admin

from.models import Choice, Question

#...
admin.site.register(Choice)

Maintenant, "Choix" est une option disponible dans l'administrateur Django. Le formulaire "Ajouter un choix" ressemble à ceci :

Add Choice form interface

Dans ce formulaire, le champ "Question" est une liste déroulante contenant toutes les questions de la base de données. Django sait qu'une ~django.db.models.ForeignKey devrait être représentée dans l'administrateur sous forme d'une liste <select>. Dans notre cas, il n'existe qu'une question pour le moment.

Notez également le lien "Ajouter une autre question" à côté de "Question". Tout objet ayant une relation ForeignKey avec un autre en bénéficie gratuitement. Lorsque vous cliquez sur "Ajouter une autre question", vous obtiendrez une fenêtre pop-up avec le formulaire "Ajouter une question". Si vous ajoutez une question dans cette fenêtre et cliquez sur "Enregistrer", Django enregistrera la question dans la base de données et l'ajoutera dynamiquement comme choix sélectionné dans le formulaire "Ajouter un choix" que vous êtes en train de consulter.

Mais, en réalité, c'est une manière inefficace d'ajouter des objets Choice au système. Il serait préférable de pouvoir ajouter plusieurs Choix directement lorsque vous créez l'objet Question. Voyons comment faire.

Supprimez l'appel register() pour le modèle Choice. Ensuite, modifiez le code d'enregistrement de Question pour qu'il ressemble à ceci :

from django.contrib import admin

from.models import Choice, Question


class ChoiceInline(admin.StackedInline):
    model = Choice
    extra = 3


class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None, {"fields": ["question_text"]}),
        ("Informations de date", {"fields": ["pub_date"], "classes": ["collapse"]}),
    ]
    inlines = [ChoiceInline]


admin.site.register(Question, QuestionAdmin)

Cela indique à Django : "Les objets Choice sont édités sur la page d'administration de Question. Par défaut, fournissez suffisamment de champs pour 3 choix."

Chargez la page "Ajouter une question" pour voir à quoi cela ressemble :

Question admin with choices

Le fonctionnement est le suivant : Il y a trois emplacements pour les Choix liés - comme spécifié par extra - et chaque fois que vous revenez sur la page "Modifier" pour un objet déjà créé, vous obtenez trois emplacements supplémentaires.

À la fin des trois emplacements actuels, vous trouverez un lien "Ajouter un autre Choix". Si vous cliquez dessus, un nouvel emplacement sera ajouté. Si vous voulez supprimer l'emplacement ajouté, vous pouvez cliquer sur la croix en haut à droite de l'emplacement ajouté. Cette image montre un emplacement ajouté :

Additional slot added dynamically

Cependant, un petit problème subsiste. Il faut beaucoup d'espace sur l'écran pour afficher tous les champs pour entrer les objets Choice liés. Pour cette raison, Django propose une manière tabulaire d'afficher les objets liés en ligne. Pour l'utiliser, modifiez la déclaration ChoiceInline pour qu'elle ressemble à ceci :

class ChoiceInline(admin.TabularInline):
  ...

Avec cette TabularInline (au lieu de StackedInline), les objets liés sont affichés dans un format plus compact, basé sur un tableau :

Tabular inline choices display

Notez qu'il y a une colonne supplémentaire "Supprimer?" qui permet de supprimer les lignes ajoutées en utilisant le bouton "Ajouter un autre Choix" et les lignes qui ont déjà été enregistrées.

Personnaliser la liste de modification de l'administrateur

Maintenant que la page d'administration de Question semble bonne, apportons quelques ajustements à la page "liste de modification" - celle qui affiche toutes les questions du système.

Voici à quoi elle ressemble pour l'instant :

Polls change list page

Par défaut, Django affiche la str() de chaque objet. Mais parfois, il serait plus utile de pouvoir afficher des champs individuels. Pour cela, utilisez l'option d'administration ~django.contrib.admin.ModelAdmin.list_display, qui est un tuple de noms de champs à afficher, en colonnes, sur la page de liste de modification de l'objet :

class QuestionAdmin(admin.ModelAdmin):
    #...
    list_display = ["question_text", "pub_date"]

Pour être sûr, ajoutons également la méthode was_published_recently() de **Configurez la base de données** :

class QuestionAdmin(admin.ModelAdmin):
    #...
    list_display = ["question_text", "pub_date", "was_published_recently"]

Maintenant, la page de liste de modification des questions ressemble à ceci :

Question change list view

Vous pouvez cliquer sur les en-têtes de colonne pour trier par ces valeurs - sauf dans le cas de l'en-tête was_published_recently, car le tri par la sortie d'une méthode arbitraire n'est pas supporté. Notez également que l'en-tête de colonne pour was_published_recently est, par défaut, le nom de la méthode (avec les tirets remplacés par des espaces), et que chaque ligne contient la représentation sous forme de chaîne de la sortie.

Vous pouvez améliorer cela en utilisant le décorateur ~django.contrib.admin.display sur cette méthode (dans polls/models.py), comme suit :

from django.contrib import admin


class Question(models.Model):
    #...
    @admin.display(
        boolean=True,
        ordering="pub_date",
        description="Publié récemment?",
    )
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now

Pour plus d'informations sur les propriétés configurables via le décorateur, consultez ~django.contrib.admin.ModelAdmin.list_display.

Modifiez à nouveau votre fichier polls/admin.py et ajoutez une amélioration à la page de liste de modification de Question : des filtres en utilisant ~django.contrib.admin.ModelAdmin.list_filter. Ajoutez la ligne suivante à QuestionAdmin :

list_filter = ["pub_date"]

Cela ajoute une barre latérale "Filtrer" qui permet aux utilisateurs de filtrer la liste de modification par le champ pub_date :

Admin list filter sidebar

Le type de filtre affiché dépend du type de champ sur lequel vous filtrez. Comme pub_date est un ~django.db.models.DateTimeField, Django sait donner des options de filtrage appropriées : "Toute date", "Aujourd'hui", "Derniers 7 jours", "Ce mois-ci", "Cette année".

Cela prend forme bien. Ajoutons une fonction de recherche :

search_fields = ["question_text"]

Cela ajoute une zone de recherche en haut de la liste de modification. Lorsque quelqu'un entre des termes de recherche, Django cherchera dans le champ question_text. Vous pouvez utiliser autant de champs que vous le souhaitez - bien que, car cela utilise une requête LIKE en arrière-plan, limiter le nombre de champs de recherche à un nombre raisonnable facilitera la recherche dans votre base de données.

Il est également opportun de noter que les listes de modification vous donnent une pagination gratuite. La valeur par défaut est d'afficher 100 éléments par page. Pagination des listes de modification <django.contrib.admin.ModelAdmin.list_per_page>, zones de recherche <django.contrib.admin.ModelAdmin.search_fields>, filtres <django.contrib.admin.ModelAdmin.list_filter>, hiérarchies de dates <django.contrib.admin.ModelAdmin.date_hierarchy> et tri des en-têtes de colonne <django.contrib.admin.ModelAdmin.list_display> fonctionnent toutes ensemble comme vous le pensez.

Personnaliser l'apparence et la sensation générale de l'administrateur

Il est clair que le fait d'avoir "Administration Django" en haut de chaque page d'administration est ridicule. C'est juste du texte de remplacement.

Cependant, vous pouvez le changer en utilisant le système de templates de Django. L'administrateur Django est alimenté par Django lui-même, et ses interfaces utilisent le système de templates propre à Django.

Personnaliser les templates de votre projet

Créez un répertoire templates dans le répertoire de votre projet (celui qui contient manage.py). Les templates peuvent être situés n'importe où sur votre système de fichiers accessible par Django. (Django s'exécute avec le nom d'utilisateur sous lequel votre serveur s'exécute.) Cependant, il est bon de suivre la convention consistant à conserver vos templates au sein du projet.

Ouvrez votre fichier de paramètres (mysite/settings.py, souvenez-vous) et ajoutez une option DIRS <TEMPLATES-DIRS> dans la configuration TEMPLATES :

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",
        "DIRS": [BASE_DIR / "templates"],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

DIRS <TEMPLATES-DIRS> est une liste de répertoires de système de fichiers à vérifier lors du chargement des templates Django ; c'est un chemin de recherche.

Organiser les templates

tout comme les fichiers statiques, nous pourrions avoir tous nos templates ensemble, dans un grand répertoire templates, et cela fonctionnerait parfaitement. Cependant, les templates qui appartiennent à une application particulière devraient être placés dans le répertoire de templates de cette application (par exemple polls/templates) plutôt que dans celui du projet (templates). Nous en discuterons plus en détail dans le tutoriel sur les applications réutilisables </intro/reusable-apps> pourquoi nous faisons cela.

Maintenant, créez un répertoire appelé admin à l'intérieur de templates, et copiez le template admin/base_site.html à partir du répertoire de templates d'administrateur par défaut dans le code source de Django lui-même (django/contrib/admin/templates) dans ce répertoire.

Où sont les fichiers sources de Django?

Si vous avez du mal à trouver où se trouvent les fichiers sources de Django sur votre système, exécutez la commande suivante :

python -c "import django; print(django.__path__)"
['/home/labex/.local/lib/python3.10/site-packages/django']

Ensuite, éditez le fichier et remplacez {{ site_header|default:_('Django administration') }} (y compris les accolades) par le nom de votre propre site tel que vous le jugez approprié. Vous devriez finir avec une section de code comme :

{% block branding %}
<div id="site-name"><a href="{% url 'admin:index' %}">Administration des sondages</a><div>
{% endblock %}

Nous utilisons cette approche pour vous apprendre à surcharger des templates. Dans un projet réel, vous utiliseriez probablement l'attribut django.contrib.admin.AdminSite.site_header pour effectuer cette personnalisation particulière plus facilement.

Ce fichier de template contient beaucoup de texte comme {% block branding %} et {{ title }}. Les balises {% et {{ font partie du langage de templates de Django. Lorsque Django rend admin/base_site.html, ce langage de templates sera évalué pour produire la page HTML finale, tout comme nous l'avons vu dans **Création des vues d'interface publique**.

Notez que n'importe quel template d'administrateur par défaut de Django peut être surchargé. Pour surcharger un template, faites comme vous l'avez fait avec base_site.html - copiez-le à partir du répertoire par défaut dans votre répertoire personnalisé, et apportez les modifications.

Personnaliser les templates de votre application

Les lecteurs perspicaces se demanderont : Mais si DIRS <TEMPLATES-DIRS> était vide par défaut, comment Django trouvait-il les templates d'administrateur par défaut? La réponse est que, puisque APP_DIRS <TEMPLATES-APP_DIRS> est définie sur True, Django recherche automatiquement un sous-répertoire templates/ à l'intérieur de chaque package d'application, pour être utilisé en cas de panne (n'oubliez pas que django.contrib.admin est une application).

Notre application de sondage n'est pas très complexe et n'a pas besoin de templates d'administrateur personnalisés. Mais si elle devenait plus sophistiquée et nécessitait la modification des templates d'administrateur standard de Django pour certaines de ses fonctionnalités, il serait plus sage de modifier les templates de l'application, plutôt que ceux du projet. Ainsi, vous pourriez inclure l'application de sondages dans tout nouveau projet et être sûr qu'elle trouverait les templates personnalisés dont elle a besoin.

Consultez la documentation sur le chargement de templates <template-loading> pour plus d'informations sur la manière dont Django trouve ses templates.

Personnaliser la page d'accueil de l'administrateur

Sur un ton similaire, vous pouvez vouloir personnaliser l'apparence et la sensation générale de la page d'accueil de l'administrateur Django.

Par défaut, elle affiche toutes les applications de INSTALLED_APPS qui ont été enregistrées auprès de l'application d'administrateur, dans l'ordre alphabétique. Vous pouvez vouloir apporter des modifications importantes à la disposition. Après tout, l'accueil est probablement la page la plus importante de l'administrateur, et elle devrait être facile à utiliser.

Le template à personnaliser est admin/index.html. (Faites comme avec admin/base_site.html dans la section précédente - copiez-le à partir du répertoire par défaut vers votre répertoire de templates personnalisé). Éditez le fichier, et vous verrez qu'il utilise une variable de template appelée app_list. Cette variable contient toutes les applications Django installées. Au lieu d'utiliser cela, vous pouvez coder en dur des liens vers les pages d'administrateur spécifiques aux objets de la manière que vous jugez la meilleure.

Sommaire

Félicitations! Vous avez terminé le laboratoire de personnalisation du site d'administration de Django. Vous pouvez pratiquer d'autres laboratoires sur LabEx pour améliorer vos compétences.