Work on the administration panels

This commit is contained in:
Fred Pauchet 2024-02-01 21:39:03 +01:00
parent c0bec85c6f
commit 3d860d6a6b
16 changed files with 203 additions and 18 deletions

View File

@ -91,12 +91,12 @@ from django.contrib import admin
from .models import Item, WishList <1>
@register(Item)
@admin.register(Item)
class ItemAdmin(admin.ModelAdmin): <2>
pass
@register(WishList)
@admin.register(WishList)
class WishListAdmin(admin.ModelAdmin):
pass
```
@ -162,7 +162,7 @@ Le titre peut être modifié de deux manières :
* Soit en ajoutant lassignation suivante dans le fichier `urls.py` :
```python
admin.site.site_header = "SuperBook Secret Area`.
admin.site.site_header = "Gwift Secret Area"
```
=== Prefetch
@ -178,31 +178,70 @@ La solution consiste à utiliser la propriété `list_select_related` de la clas
=== Laffichage
Comme linterface dadministration fonctionne (en trèèèès) gros comme un
CRUD auto-généré, nous trouvons par défaut la possibilité de :
Comme linterface dadministration fonctionne (en trèèèès) gros comme un CRUD auto-généré, nous trouvons par défaut la possibilité de :
. Créer de nouveaux éléments
. Lister les éléments existants
. Modifier des éléments existants
. Supprimer un élément en particulier.
Les affichages sont donc de deux types : en liste et au détail.
image::django/admin/django-admin-base.png[align="center"]
Les affichages sont donc de deux types :
* En liste, pour afficher et filtrer sur certains éléments
* Les détails d'un élément.
==== Affichage en liste
Pour les affichages en liste, le plus simple consiste à jouer sur la propriété `list_display`, afin de personnaliser les informations que nous visualiserons dans le tableau affiché :
Par défaut, l'affichage en liste se base sur la propriété `__str__()` de chaque élément, afin d'en proposer une représentation textuelle.
Cette représentation est cependant totalement impersonnelle, n'a aucun intérêt et ce sera sans doute la première chose que vous modifierez dans votre projet tout neuf.
image::django/admin/django-base-list.png[align="center"]
Pour ce type d'affichage, le plus simple consiste à jouer sur la propriété `list_display`, afin de personnaliser les informations que nous visualiserons dans le tableau affiché :
```python
[...]
@admin.register(Item)
class ItemAdmin(admin.ModelAdmin): <2>
list_display = ("__str__", "wishlist_name")
list_filter = ("wishlist_name",)
[...]
```
image::django/admin/django-list_display.png[align="center"]
[WARNING]
====
Il n'est pas possible d'afficher tout et n'importe quoi sans un peu de configuration.
Par exemple, si nous souhaitons afficher le nom de la liste dont dépend l'élément ou une propriété relative, il est nécessaire de passer par une méthode au niveau de la classe d'administration.
```python
@admin.register(Item)
class ItemAdmin(admin.ModelAdmin):
def wishlist_name(self, obj): <1>
return obj.wishlist.name
list_display = ("__str__", "wishlist_name") <2>
```
<1> Nous définissons une méthode `wishlist_name`
<2> à laquelle nous faisons référence dans la propriété `list_display`.
L'objectif ici est de pouvoir *tester* tout comportement qui sortirait des sentiers battus.
====
[NOTE]
====
Par défaut, la première colonne va accueillir le lien vers le formulaire dédition. Nous pouvons donc modifier ceci, voire créer de nouveaux liens vers dautres éléments en construisant des URLs dynamiquement.
====
==== Affichage des détails d'un élément
*... montrer le regroup_by et les collapse.*
=== Filtres
==== Filtres de listes
Chaque liste permet de spécifier des filtres spécifiques; ceux-ci peuvent être :
@ -211,16 +250,61 @@ Chaque liste permet de spécifier des filtres spécifiques; ceux-ci peuvent êtr
. *Verticaux* (`filter_vertical`)
. *Temporels* (`date_hierarchy`)
==== Appliqués à la liste
===== Appliqués à la liste
==== Horizontaux
La version la plus simple des filtres consiste à définir une propriété `list_filter` au niveau de la classe `ModelAdmin` :
==== Verticaux
```python
[...]
==== Temporels
@admin.register(Item)
class ItemAdmin(admin.ModelAdmin):
list_display = ("__str__", "wishlist_name")
list_filter = ("wishlist__name",) <1>
==== Conclusions
[...]
```
<1> `list_filter` est un tuple, qui prend autant de valeurs que nous souhaitons définir de filtres différents. Nous utilisons ici un _lookup_ de type `__` pour définir précisément sur quel champ nous souhaitons pouvoir appliquer un filtre.
image::django/admin/django-list-filter.png[align="center"]
===== Temporels
Les filtres temporels ajoutent la possibilité de naviguer chronologiquement parmi des données.
Il sera nécessaire de leur donner des informations horodatées, comme par exemple une date de création ou de modification :
```python
[...]
@admin.register(Item)
class ItemAdmin(admin.ModelAdmin):
list_display = ("__str__", "wishlist_name")
list_filter = ("wishlist__name",)
date_hierarchy = "modified_at" <1>
[...]
```
<1> Cette propriété-ci prend comme valeur le nom d'une propriété typé comme étant une date ou un moment. Il ne s'agit donc pas d'un tuple ou d'une liste !
image::django/admin/date-hierarchy.png[align="center"]
===== Filtres horizontaux
Les filtres horizontaux sont représentés par des clés de type `ManyToMany`.
Le prérequis sera donc de disposer d'un champ de ce type-là.
===== Filtres verticaux
Idem pour les filtres verticaux, qui se basent également des champs de type `ManyToMany`, mais qui représenteront l'information verticalement.
===== Conclusions
==== Affichage des détails d'un élément
*... montrer le regroup_by et les collapse.*
=== Permissions

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

View File

@ -37,6 +37,7 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
"wish",
]
MIDDLEWARE = [

View File

18
src/generic/wish/admin.py Normal file
View File

@ -0,0 +1,18 @@
from django.contrib import admin
from .models import Item, WishList
admin.site.site_header = "Gwift Secret Area"
@admin.register(Item)
class ItemAdmin(admin.ModelAdmin):
list_display = ("__str__", "wishlist")
list_filter = ["wishlist__name"]
date_hierarchy = "modified_at"
@admin.register(WishList)
class WishListAdmin(admin.ModelAdmin):
pass

6
src/generic/wish/apps.py Normal file
View File

@ -0,0 +1,6 @@
from django.apps import AppConfig
class WishConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'wish'

View File

@ -0,0 +1,30 @@
# Generated by Django 5.0.1 on 2024-02-01 19:26
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='WishList',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
],
),
migrations.CreateModel(
name='Item',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255)),
('wishlist', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='wish.wishlist')),
],
),
]

View File

@ -0,0 +1,25 @@
# Generated by Django 5.0.1 on 2024-02-01 20:30
import django.utils.timezone
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('wish', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='item',
name='created_at',
field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
preserve_default=False,
),
migrations.AddField(
model_name='item',
name='modified_at',
field=models.DateTimeField(auto_now=True),
),
]

View File

View File

@ -0,0 +1,15 @@
from django.db import models
class WishList(models.Model):
name = models.CharField(max_length=255)
def __str__(self):
return self.name
class Item(models.Model):
name = models.CharField(max_length=255)
wishlist = models.ForeignKey(WishList, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)

View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

View File

@ -0,0 +1,3 @@
from django.shortcuts import render
# Create your views here.