gwift-book/source/part-3-data-model/admin.adoc

11 KiB
Executable File
Raw Blame History

Administration

Woké. On va commencer par la partie à ne surtout (surtout !!) pas faire en premier dans un projet Django. Mais on va la faire quand même: la raison principale est que cette partie est tellement puissante et performante, quelle pourrait laisser penser quil est possible de réaliser une application complète rien quen configurant ladministration. Mais cest faux.

Ladministration est une sorte de tour de contrôle évoluée, un back office sans transpirer; elle se base sur le modèle de données programmé et construit dynamiquement les formulaires qui lui est associé. Elle joue avec les clés primaires, étrangères, les champs et types de champs par introspection, et présente tout ce quil faut pour avoir du CRUD, cest-à-dire tout ce quil faut pour ajouter, lister, modifier ou supprimer des informations.

Son problème est quelle présente une courbe dapprentissage asymptotique. Il est très facile darriver rapidement à un bon résultat, au travers dun périmètre de configuration relativement restreint. Mais quoi que vous fassiez, il y a un moment où la courbe de paramétrage sera tellement ardue que vous aurez plus facile à développer ce que vous souhaitez ajouter en utilisant les autres concepts de Django.

Cette fonctionnalité doit rester dans les mains dadministrateurs ou de gestionnaires, et dans leurs mains à eux uniquement: il nest pas question de donner des droits aux utilisateurs finaux (même si cest extrêment tentant durant les premiers tours de roues). Indépendamment de la manière dont vous allez lutiliser et la configurer, vous finirez par devoir développer une "vraie" application, destinée aux utilisateurs classiques, et répondant à leurs besoins uniquement.

Une bonne idée consiste à développer ladministration dans un premier temps, en gardant en tête quil sera nécessaire de développer des concepts spécifiques. Dans cet objectif, ladministration est un outil exceptionel, qui permet de valider un modèle, de créer des objets rapidement et de valider les liens qui existent entre eux.

Cest aussi un excellent outil de prototypage et de preuve de concept.

Elle se base sur plusieurs couches que lon a déjà (ou on va bientôt) aborder (suivant le sens de lecture que vous préférez):

  1. Le modèle de données

  2. Les validateurs

  3. Les formulaires

  4. Les widgets

Le modèle de données

Comme expliqué ci-dessus, le modèle de données est constité dun ensemble de champs typés et de relations. Ladministration permet de décrire les données qui peuvent être modifiées, en y associant un ensemble (basique) de permissions.

Si vous vous rappelez de lapplication que nous avions créée dans la première partie, les URLs reprenaient déjà la partie suivante:

from django.contrib import admin
from django.urls import path

from gwift.views import wish_details

urlpatterns = [
    path('admin/', admin.site.urls), (1)
    [...]
]
  1. Cette URL signifie que la partie admin est déjà active et accessible à lURL <mon_site>/admin

Cest le seul prérequis pour cette partie.

Chaque application nouvellement créée contient par défaut un fichier admin.py, dans lequel il est possible de déclarer quel ensemble de données sera accessible/éditable. Ainsi, si nous partons du modèle basique que nous avions détaillé plus tôt, avec des souhaits et des listes de souhaits:

# gwift/wish/models.py

from django.db import models


class WishList(models.Model):
    name = models.CharField(max_length=255)


class Item(models.Model):
    name = models.CharField(max_length=255)
    wishlist = models.ForeignKey(WishList, on_delete=models.CASCADE)

Nous pouvons facilement arriver au résultat suivant, en ajoutant quelques lignes de configuration dans ce fichier admin.py:

from django.contrib import admin

from .models import Item, WishList (1)


admin.site.register(Item) (2)
admin.site.register(WishList)
  1. Nous importons les modèles que nous souhaitons gérer dans ladmin

  2. Et nous les déclarons comme gérables. Cette dernière ligne implique aussi quun modèle pourrait ne pas être disponible du tout, ce qui nactivera simplement aucune opération de lecture ou modification.

Il nous reste une seule étape à réaliser: créer un nouvel utilisateur. Pour cet exemple, notre gestion va se limiter à une gestion manuelle; nous aurons donc besoin dun super-utilisateur, que nous pouvons créer grâce à la commande python manage.py createsuperuser.

λ python manage.py createsuperuser
Username (leave blank to use 'fred'): fred
Email address: fred@root.org
Password: ******
Password (again): ******
Superuser created successfully.
django site admin
Figure 1. Connexion au site dadministration
django site admin after connection
Figure 2. Administration

Quelques conseils de base

  1. Surchargez la méthode str(self) pour chaque classe que vous aurez définie dans le modèle. Cela permettra de construire une représentation textuelle pour chaque instance de votre classe. Cette information sera utilisée un peu partout dans le code, et donnera une meilleure idée de ce que lon manipule. En plus, cette méthode est également appelée lorsque ladministration historisera une action (et comme cette étape sera inaltérable, autant quelle soit fixée dans le début).

  2. La méthode get_absolute_url(self) retourne lURL à laquelle on peut accéder pour obtenir les détails dune instance. Par exemple:

def get_absolute_url(self):
    return reverse('myapp.views.details', args=[self.id])
  1. Les attributs Meta:

class Meta:
	ordering = ['-field1', 'field2']
	verbose_name = 'my class in singular'
	verbose_name_plural = 'my class when is in a list!'
  1. Le titre:

    • Soit en modifiant le template de ladministration

    • Soit en ajoutant lassignation suivante dans le fichier urls.py: admin.site.site_header = "SuperBook Secret Area.

  2. Prefetch

En gros, le problème de ladmin est que si on fait des requêtes imbriquées, on va flinguer lapplication et le chargement de la page. La solution consiste à utiliser la propriété list_select_related de la classe dAdmin, afin dappliquer une jointure par défaut et et gagner en performances.

admin.ModelAdmin

La classe admin.ModelAdmin que lon retrouvera principalement dans le fichier admin.py de chaque application contiendra la définition de ce que lon souhaite faire avec nos données dans ladministration. Cette classe (et sa partie Meta)

Laffichage

Comme linterface dadministration fonctionne (en trèèèès) gros comme un CRUD auto-généré, on trouve par défaut la possibilité de :

  1. Créer de nouveaux éléments

  2. Lister les éléments existants

  3. Modifier des éléments existants

  4. Supprimer un élément en particulier.

Les affichages sont donc de deux types: en liste et par élément.

Pour les affichages en liste, le plus simple consiste à jouer sur la propriété list_display.

Par défaut, la première colonne va accueillir le lien vers le formulaire dédition. On peut donc modifier ceci, voire créer de nouveaux liens vers dautres éléments en construisant des URLs dynamiquement.

(Insérer ici lexemple de Medplan pour les liens vers les postgradués :-))

Voir aussi comment personnaliser le fil dAriane ?

Les filtres

  1. list_filter

  2. filter_horizontal

  3. filter_vertical

  4. date_hierarchy

Les permissions

On la dit plus haut, il vaut mieux éviter de proposer un accès à ladministration à vos utilisateurs. Il est cependant possible de configurer des permissions spécifiques pour certains groupes, en leur autorisant certaines actions de visualisation/ajout/édition ou suppression.

Cela se joue au niveau du ModelAdmin, en implémentant les méthodes suivantes:

def has_add_permission(self, request):
	return True

def has_delete_permission(self, request):
	return True

def has_change_permission(self, request):
	return True

On peut accéder aux informations de lutilisateur actuellement connecté au travers de lobjet request.user.

  1. NOTE: ajouter un ou deux screenshots :-)

Les relations

Les relations 1-n

Les relations 1-n sont implémentées au travers de formsets (que lon a normalement déjà décrits plus haut). Ladministration permet de les définir dune manière extrêmement simple, grâce à quelques propriétés.

Limplémentation consiste tout dabord à définir le comportement du type dobjet référencé (la relation -N), puis à inclure cette définition au niveau du type dobjet référençant (la relation 1-).

class WishInline(TabularInline):
	model = Wish


class Wishlist(admin.ModelAdmin):
	...
	inlines = [WishInline]
	...

Et voilà : ladministration dune liste de souhaits (Wishlist) pourra directement gérer des relations multiples vers des souhaits.

Les auto-suggestions et auto-complétions

Parler de lintégration de select2.

La présentation

Parler ici des fieldsets et montrer comment on peut regrouper des champs dans des groupes, ajouter un peu de javascript, …​

Les actions sur des sélections

Les actions permettent de partir dune liste déléments, et autorisent un utilisateur à appliquer une action sur une sélection déléments. Par défaut, il existe déjà une action de suppression.

Les paramètres dentrée sont :

  1. Linstance de classe

  2. La requête entrante

  3. Le queryset correspondant à la sélection.

def double_quantity(self, request, queryset):
	for obj in queryset.all():
		obj.field += 1
		obj.save()
double_quantity.short_description = "Doubler la quantité des souhaits."

Et pour informer lutilisateur de ce qui a été réalisé, on peut aussi lui passer un petit message:

if rows_updated = 0:
	self.message_user(request, "Aucun élément n'a été impacté.")
else:
	self.message_user(request, "{} élément(s) mis à jour".format(rows_updated))

La documentation

Nous lavons dit plus haut, ladministration de Django a également la possibilité de rendre accessible la documentation associée à un modèle de données. Pour cela, il suffit de suivre les bonnes pratiques, puis dactiver la documentation à partir des URLs: