Documentation de Django 1.1.1

Écrire votre première application Django, partie 2

Ce tutoriel commence là où le Tutoriel 1 s’achève. Nous continuons l’application de sondage Web et allons nous focaliser sur le site d’administration généré automatiquement par Django.

Philosophie

La génération de sites d’admin pour votre équipe ou vos clients pour ajouter, modifier et suprimer du contenu est un travail pénible qui ne requiert pas beaucoup de créativité. C’est pour cette raison que Django automatise entièrement la création des interfaces d’administration des modèles.

Django a été écrit dans un environnement éditorial, avec une très nette séparation entre les « éditeurs de contenu » et le site « public ». Les gestionnaires du site utilisent le système pour ajouter des nouvelles, des histoires, des événements, des résultats sportifs, etc., et ce contenu est affiché sur le site public. Django résoud le problème de création d’une interface uniforme pour les administrateurs du site qui éditent le contenu.

L’interface d’admin n’est pas nécessairement destinée a être utilisée par les visiteurs du site ; c’est pour les gestionnaires du site.

Activer le site d’admin

Le site d’admin de Django n’est pas activé par défaut – c’est une fonctionnalité optionnelle. Pour activer le site d’admin dans votre installation, suivez ces trois points:

  • Ajoutez "django.contrib.admin" dans votre option INSTALLED_APPS.

  • Lancez python manage.py syncdb. Puisque vous avez ajouté une nouvelle application à INSTALLED_APPS, les tables de la base de données ont besoin d’être mises à jour.

  • Éditez votre fichier monsite/urls.py et décommentez la ligne en dessous de « Uncomment the next two lines... ». Ce fichier est une URLconf; nous creuserons le sujet des URLconfs dans le prochain tutoriel. Pour l’instant, tout ce que vous avez besoin de savoir est qu’il définit la racine des URLs de vos applications. A la fin, vous devriez avoir un fichier urls.py qui ressemble à ceci :

    from django.conf.urls.defaults import *
    
    # Uncomment the next two lines to enable the admin:
    from django.contrib import admin
    admin.autodiscover()
    
    urlpatterns = patterns('',
        # Example:
        # (r'^mysite/', include('mysite.foo.urls')),
    
        # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
        # to INSTALLED_APPS to enable admin documentation:
        # (r'^admin/doc/', include('django.contrib.admindocs.urls')),
    
        # Uncomment the next line to enable the admin:
        (r'^admin/(.*)', admin.site.root),
    )
    

    (Les lignes en gras sont celles qui doivent être décommentées.)

Démarrer le serveur de développement

Démarrons le serveur de développement et explorons le site d’administration.

Rappel du Tutoriel 1 : vous démarrez le serveur de développement comme ceci:

python manage.py runserver

À présent, ouvrez un navigateur Web et allez au « /admin/ » de votre domaine local -- par exemple, http://127.0.0.1:8000/admin/. Vous devriez voir l'écran de connexion à l'interface d'admin:

L'écran de connexion à l'interface d'admin de Django

Entrez dans le site d'admin

Maintenant, essayez de vous identifier (vous avez créé un compte superutilisateur dans la première partie du tutoriel vous vous rappelez ? Si vous n'en avez pas créé ou que vous avez oublié le mot de passe vous pouvez en créer un nouveau - en). Vous devriez voir la page d'index de l'interface d'admin de Django:

La page d'index de l'interface d'admin de Django

Par défaut, vous devriez voir deux types de contenu éditable : groupes et utilisateurs. Ce sont des caractéristiques du noyau que Django intègre par défaut.

Rendre l'appli de sondage modifiable via l'interface d'admin

Mais où est notre appli de sondage ? Il n'est pas affiché sur la page d'index de l'interface d'admin.

Juste une chose à faire : Nous avons besoin de spécifier dans le modèle Poll que les objets Poll ont une interface d'admin. Pour faire ceci, créez un fichier admin.py dans votre répertoire polls, et éditez-le de la manière suivante :

from mysite.polls.models import Poll
from django.contrib import admin

admin.site.register(Poll)

Vous aurez besoin de redémarrer le serveur de développement pour voir vos changements. Normalement, le serveur redémarre automatiquement à chaque fois que vous modifiez un fichier, mais la création d'un nouveau fichier ne déclenche pas ce redémarrage.

Explorer les fonctionnalités libres de l'interface d'admin

Maintenant que nous avons inscrit Poll dans l'interface d'admin, Django sait qu'il devrait être affiché sur la page d'index:

La page d'index du site d'admin de Django, maintenant avec les sondages d'affichés

Cliquez sur « Polls ». À présent, vous êtes sur la page « liste » des sondages. Cette page affiche tous les sondages de la base de données et vous permet d'en choisir un pour l'éditer. Il y a le sondage « Quoi de neuf ? » que nous avons créé dans le premier tutoriel:

La page de listage pour modification

Cliquez sur le sondage « Quoi de neuf ? » pour l'éditer :

Formulaire d'édition pour un objet sondage poll

A noter ici:

  • Le formulaire est généré automatiquement depuis le modèle Poll.
  • Les différents types de champs du modèle (models.DateTimeField, models.CharField) correspondent au widget d'entrée HTML approprié. Chaque type de champ sait comment s'afficher dans l'interface d'admin de Django.
  • Chaque DateTimeField reçoit des raccourcis Javascript libres. Les dates obtiennent un raccourci « Aujourd'hui » et un calendrier en popup, et les heures obtiennent un raccourci « Maintenant » et une popup pratique qui liste les heures couramment saisies.

La partie inférieure de la page vous propose une série d'opérations:

  • Sauver -- Sauvegarde les modifications et retourne à la page de listage pour modification pour ce type d'objet.
  • Sauver et continuer les modifications -- Sauvegarde les modifications et recharge la page d'administration de cet objet.
  • Sauver et ajouter un nouveau -- Sauvegarde les modifications et charge un nouveau formulaire vierge pour ce type d'objet.
  • Supprimer -- Affiche la page de confirmation de la suppression.

Changez la « Date de publication » en cliquant sur les raccourcis « Aujourd'hui » et « Maintenant ». Puis cliquez sur « Sauver et continuer les modifications ». Ensuite, cliquez sur « Historique » en haut à droite de la page. Vous verrez une page listant toutes les modifications effectuées sur cet objet via l'interface d'administration de Django, accompagnées des date et heure, ainsi que du nom de l'utilisateur qui a fait ce changement:

La page d'historique pour l'objet de sondage poll

Personnaliser le formulaire d'administration

Prenez quelques minutes pour vous émerveiller devant le code que vous n'avez pas dû écrire. Quand vous appelez admin.site.register(Poll), Django "devine" comment l'afficher dans l'interface d'administration. Souvent vous voudrez controller le look et le fonctionnement de l'interface; vous ferez ceci en communiquant à Django les options lors de l'inscription de l'objet.

Voyons voir comment cela fonctionne, en réordonnant les champs sur le formulaire d'édition. Remplacez la ligne admin.site.register(Poll) avec:

class PollAdmin(admin.ModelAdmin):
    fields = ['pub_date', 'question']

admin.site.register(Poll, PollAdmin)

Vous suivrez cette méthode -- c'est à dire, créer un objet d'administration de modèle, puis le passer en tant que deuxième paramètre de admin.site.register() -- à chaque fois que vous aurez besoin de changer les options d'administration pour un objet.

Cela fait que la « Date de publication » apparaît en premier au lieu d'être en second:

Les champs ont été réordonnés

Ce n'est pas spécialement impressionnant avec seulement deux champs, mais pour un formulaire d'administration avec des douzaines de champs, choisir un ordre intuitif est un détail d'utilisation important.

Et en parlant de formulaires avec des douzaines de champs, vous voudriez sûrement séparer le formulaire en plusieurs sous-ensembles:

class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date']}),
    ]

admin.site.register(Poll, PollAdmin)

Le premier élément de chaque tuple dans fields est le titre de la sous-partie. Voici ce à quoi notre formulaire ressemble à présent:

Le formulaire a des sous-sensembles de champs à présent

Vous pouvez assigner des classes HTML arbitraires à chaque sous-ensemble. Django fournit une classe "collapse" qui affiche un sous-ensemble particulier, initialement replié. C'est une fonctionnalité utile lorsque vous avez un long formulaire qui contient un certain nombre de champs qui ne sont pas couramment utilisés:

class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]
Le sous-ensemble est initialement replié

Ajout d'objets liés

OK, nous avons notre page d'administration de sondages Poll. Mais un sondage Poll possède plusieurs choix Choices, et la page d'admin n'affiche aucun choix.

Pour le moment.

Il y a deux façon de résoudre ce problème. Le premier et de donner au modèle Choice sa propre classe interne Admin, tout comme nous l'avons fait pour Poll. Voici ce que ça donnerait:

from mysite.polls.models import Choice

admin.site.register(Choice)

Maintenant les choix sont une option disponible dans l'interface d'admin de Django. Le formulaire « Add choice » ressemble à ceci:

Page d'administration de Choice

Dans ce formulaire, le champ « Poll » est une boîte de sélection contenant tous les sondages de la base de données. Django sait qu'une instance de ForeignKey devrait être représentée dans l'interface d'admin par une boîte <select>. Dans notre cas, seul un sondage existe à ce point.

Notez également le lien « Add another » à côté de « Poll ». Chaque objet avec une relation ForeignKey vers un autre reçoit ce lien gratuitement. Quand vous cliquez sur « Add another », vous obtiendrez une fenêtre en popup quand le formulaire « Add poll ». Si vous ajoutez un sondage dans cette fenêtre et que vous cliquez sur « Sauver », Django sauvegardera le sondage dans la base de données et l'ajoutera dynamiquement comme choix sélectionné dans le formulaire « Add choice » que vous étiez en train de remplir.

Mais, franchement, c'est une manière inefficace d'ajouter des objets « Choice » dans le système. Ça serait mieux si vous pouviez ajouter un groupe de choix « Choices » directement lorsque vous créez l'objet « Poll ». Faisons de cette façon.

Retirez l'appel register() du modèle Choice. Puis, éditez le code d'enregistrement de Poll comme ceci:

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

class PollAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question']}),
        ('Date information', {'fields': ['pub_date'], 'classes': ['collapse']}),
    ]
    inlines = [ChoiceInline]

admin.site.register(Poll, PollAdmin)

Ça dit à Django: « Les objets Choice sont édités dans la page d'administration de Poll. Par défaut, fournir assez de champs pour 3 choix ».

Charger la page « Add poll » pour voir à quoi ça ressemble:

La page d'ajout de sondage contient maintenant des choix

Ça marche comme ceci : Il y a trois compartiments pour les choix « Choices » liés -- comme spécifié par extra -- et chaque fois que vous revenez sur la page « Changement » d'un objet déjà créé, vous obtenez trois compartiments supplémentaires.

Un petit problème cependant. Ça prend beaucoup de place d'afficher tous les champs pour saisir les objets « Choice » liés. C'est pour cette raison que Django offre une alternative d'affichage en ligne des objets liés:

class ChoiceInline(admin.TabularInline):
    #...

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

La page d'ajout de sondage a maintenant des choix plus compacts

Personnaliser la liste pour modification de l'interface d'admin

Maintenant que la page d'admin des sondage « Poll » a un bon look, arrangeons un peu la page de « listage pour modification » -- celle qui affiche tous les sondages du système.

Voici à quoi ça ressemble à ce point:

La page de listage pour modification des sondages Poll

Par défaut, Django affiche le str() de chaque objet. Mais parfois, ça serait plus utile si nous pouvions afficher des champs individuels. Dans ce but, utilisez l'option list_display, qui est un tuple de nom de champs à afficher, en colonnes, sur la page de listage pour modification de l'objet:

class PollAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question', 'pub_date')

Juste pour la démonstration, incluons également la méthode perso was_published_today du Tutoriel 1:

class PollAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question', 'pub_date', 'was_published_today')

À présent la page de listage pour modification des sondage ressemble à ceci:

La page de listage pour modification, mise à jour

Vous pouvez cliquer sur les en-têtes de colonne pour trier selon ces valeurs -- sauf dans le cas de l'en-tête was_published_today, parce que le tri selon le résultat d'une méthode arbitraire n'est pas supporté. Notez aussi que l'en-tête de la colonne pour was_published_today est, par défaut, le nom de la méthode (avec les underscores remplacés par des espaces. Mais vous pouvez changer cela en donnant à cette méthode un attribut short_description:

def was_published_today(self):
    return self.pub_date.date() == datetime.date.today()
was_published_today.short_description = u'Publié aujourd\'hui ?'

Ajoutons une nouvelle amélioration à la page de listage pour modification de sondages : des filtres. Ajoutez la ligne suivante à Poll.Admin:

list_filter = ['pub_date']

Cela ajoute une sidebar « Filter » qui permet aux gens de filtrer la liste pour modification selon le champ pub_date:

La page de listage pour modification de sondages, mise à jour

Le type de filtre affiché dépend du type de champs que vous êtes en train de filtrer. Parce que pub_date est un DateTimeField, Django sait donner les options de filtrage par défaut pour les DateTimeFields: « Toutes les dates », « Aujourd'hui », « Les 7 derniers jours », « Ce mois-ci », « Cette année ».

Ça a meilleure forme. Ajoutons une fonctionnalité de recherche:

search_fields = ['question']

Cela ajoute une boîte de recherche en haut de la liste pour modification. Quand quelqu'un saisit des termes de recherche, Django va rechercher dans le champ question. Vous pouvez indiquer autant de champs que vous le désirez -- bien qu'il utilise un requête LIKE derrière, restez raisonnable pour garder votre base de données performante.

Enfin, parce que les objets « Poll » ont des dates, il serait pratique d'effectuer un classement par date. Ajoutez cette ligne:

date_hierarchy = 'pub_date'

Cela ajoute une navigation hiérarchique, par date, en haut de la page de listage pour modification. Au premier niveau, il affiche toutes les années disponibles. Puis il affine le classement en mois et, finalement, en jours.

C'est maintenant le bon moment de noter que les listes pour modification vous laissent une grande liberté de pagination. Par défaut, 50 items sont affichés par page. La pagination des listes pour modification, les boîtes de recherche, les filtres, les hiérarchies calendaires et le tri selon l'en-tête de colonne, tout fonctionne ensemble comme vous pensez qu'ils le devraient.

Personnaliser l'apparence de l'interface d'administration

Clairement, avoir « Django administration » en haut de chaque page d'administration est ridicule. C'est juste du texte de substitution.

C'est facile à modifier, cependant, en utilisant le système de template de Django. Le site d'administration de Django est fait en Django lui-même, et ses interfaces utilisent le système de template propre à Django. (Cela devient métaphysique !)

Ouvrez votre fichier de configuration (monsite/settings.py, souvenez-vous) et examinez l'option TEMPLATE_DIRS. TEMPLATE_DIRS est un tuple de répertoires du système de fichiers pour vérifier d'où les templates Django sont chargées. C'est un chemin de recherche.

Par défaut, TEMPLATE_DIRS est vide. Donc, ajoutons-lui une ligne pour dire à Django où nos templates sont situées:

TEMPLATE_DIRS = (
    "/home/monlogin/mestemplates", # Remplacez par votre propre répertoire.
)

À présent, copiez la template admin/base_site.html depuis le répertoire par défaut des templates de l'interface d'admin de Django (django/contrib/admin/templates) vers un sous-répertoire admin se trouvant dans le répertoire que vous avez défini dans TEMPLATE_DIRS. Par exemple, si votre TEMPLATE_DIRS contient "/home/mestemplates", comme ci-dessus, copiez django/contrib/admin/templates/admin/base_site.html vers /home/mytemplates/admin/base_site.html. N'oubliez pas de créer au préalable ce sous-répertoire admin.

Ensuite, éditez simplement le fichier et remplacez le texte générique de Django par le nom et l'URL de votre propre site.

Notez que tous les templates de l'interface d'admin par défaut de Django peuvent être remplacés. Pour remplacer un template, faites simplement la même chose qu'avec base_site.html -- copiez le depuis le répertoire par défaut dans votre répertoire personnel, et faites les modifications.

Les lecteurs avisés demanderont : Mais si TEMPLATE_DIRS était vide par défaut, comment Django trouvait-il les templates par défaut de l'interface d'admin ? La réponse est que, par défaut, Django regarde automatiquement dans un éventuel sous-répertoire templates/ à l'intérieur de chaque paquetage d'appli, pour l'utiliser en dernier recours. Lisez la documentation sur les types de chargeur (en) pour des informations complètes.

Personnaliser la page d'index de l'interface d'admin

De la même manière, vous voudriez sûrement personnaliser l'apparence de la page d'index de l'interface d'admin de Django.

Par défaut, il affiche toutes les applis de INSTALLED_APPS qui ont été enregistrées avec l'application admin, par ordre alphabétique. Vous voudrez sans doute faire des modifications significatives sur la mise en page. Après tout, la page d'index est probablement la page la plus importante du site d'administration, donc autant qu'elle soit facile à utiliser.

Le template à personnaliser est admin/index.html. (Faites la même chose qu'avec admin/base_site.html dans la précédente section -- copiez le depuis le répertoire par défaut vers votre répertoire de templates personnels.) Éditez le fichier, et vous verrez qu'il est utilisé une variable de template appelée app_list. Cette variable contient toutes les appli Django installées et enregistrées. Au lieu d'utiliser ça, vous pouvez écrire en dur les liens vers les pages d'administration spécifiques aux objets de la meilleure manière que vous pensez.

Lorsque vous vous serez familiarisé avec le site d'administration, lisez la partie 3 de ce tutoriel pour commencer à travailler avec les vues publiques du sondage.