Différences
Ci-dessous, les différences entre deux révisions de la page.
| Les deux révisions précédentes Révision précédente Prochaine révision | Révision précédente | ||
| public:appro-s7:td_web_hamsters [2023/11/04 16:44] – edauce | public:appro-s7:td_web_hamsters [2024/11/02 17:03] (Version actuelle) – [Indications] edauce | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| + | ===== Autonomie 1 : Une galerie en Django ===== | ||
| + | En vous basant sur l' | ||
| + | |||
| + | Exemples d' | ||
| + | * Jeu de rôle | ||
| + | * Tamagotchi | ||
| + | * Pet shop | ||
| + | * Pocket Monster | ||
| + | * Aquarium | ||
| + | * Elevage d' | ||
| + | * Course hippique | ||
| + | * Equipe de foot | ||
| + | * Athlètes | ||
| + | * etc. | ||
| + | |||
| + | Vous pouvez bien sûr conserver la structure de base qui est d' | ||
| + | |||
| + | Les personnages passent par différents états au cours de la journée en fonction des lieux qu'ils visitent. | ||
| + | |||
| + | <note tip> ** Rappel ** | ||
| + | |||
| + | Reprenez cette structure de données de type '' | ||
| + | {{ : | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | ==== Indications ==== | ||
| + | Créez un projet ' | ||
| + | |||
| + | === model.py === | ||
| + | <code python> | ||
| + | from django.db import models | ||
| + | |||
| + | class Equipement(models.Model): | ||
| + | id_equip = models.CharField(max_length=100, | ||
| + | disponibilite = models.CharField(max_length=20) | ||
| + | photo = models.CharField(max_length=200) | ||
| + | def __str__(self): | ||
| + | return self.id_equip | ||
| + | |||
| + | |||
| + | class Character(models.Model): | ||
| + | id_character = models.CharField(max_length=100, | ||
| + | etat = models.CharField(max_length=20) | ||
| + | type = models.CharField(max_length=20) | ||
| + | team = models.CharField(max_length=20) | ||
| + | photo = models.CharField(max_length=200) | ||
| + | lieu = models.ForeignKey(Equipement, | ||
| + | def __str__(self): | ||
| + | return self.id_character | ||
| + | </ | ||
| + | |||
| + | |||
| + | Vous deviez obtenir une interface simple de ce type: | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | Il est bien sûr possible d' | ||
| + | |||
| + | <note tip> | ||
| + | La mise en page du site repose sur l' | ||
| + | * {{https:// | ||
| + | * {{https:// | ||
| + | * et : {{https:// | ||
| + | * {{https:// | ||
| + | * (voir aussi ce {{https:// | ||
| + | </ | ||
| + | |||
| + | Vous pouvez exploiter les photos qui sont définies dans les attributs du modèle pour obtenir par exemple: | ||
| + | |||
| + | {{ : | ||
| + | |||
| + | ==== Formulaires Django ==== | ||
| + | (repris du tutoriel | ||
| + | |||
| + | La dernière chose que nous voulons faire sur notre site web, c'est créer une manière de mettre a jour l'etat des personnages. Les formulaires (forms) vont nous permettre de rendre le site dynamique ! | ||
| + | |||
| + | Comme toutes les choses importantes dans Django, les formulaires ont leur propre fichier : '' | ||
| + | |||
| + | Nous allons devoir créer un fichier avec ce nom dans notre dossier blog. | ||
| + | |||
| + | playground | ||
| + | └── forms.py | ||
| + | |||
| + | Ouvrez maintenant ce fichier dans l' | ||
| + | |||
| + | <code python> | ||
| + | from django import forms | ||
| + | |||
| + | from .models import Character | ||
| + | |||
| + | class MoveForm(forms.ModelForm): | ||
| + | |||
| + | class Meta: | ||
| + | model = Character | ||
| + | fields = (' | ||
| + | </ | ||
| + | Tout d' | ||
| + | |||
| + | Comme vous l'avez probablement deviné, '' | ||
| + | |||
| + | Ensuite, nous avons la class Meta qui nous permet de dire à Django quel modèle il doit utiliser pour créer ce formulaire ('' | ||
| + | |||
| + | Enfin, nous précisions quel⋅s sont le⋅s champ⋅s qui doivent figurer dans notre formulaire. Dans notre cas, nous souhaitons que seul le lieu apparaisse dans notre formulaire. | ||
| + | |||
| + | Et voilà, c'est tout ! Tout ce qu'il nous reste à faire, c'est d' | ||
| + | |||
| + | Nous allons donc une nouvelle fois suivre le processus suivant et créer : un lien vers la page, une URL, une vue et un template. | ||
| + | |||
| + | ==== Lien vers une page contenant le formulaire ==== | ||
| + | |||
| + | Il est temps d' | ||
| + | <code html> | ||
| + | <a href=" | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== URL ==== | ||
| + | Ouvrez le fichier < | ||
| + | <code python> | ||
| + | from django.urls import path | ||
| + | from . import views | ||
| + | |||
| + | urlpatterns = [ | ||
| + | path('', | ||
| + | path(' | ||
| + | path(' | ||
| + | ] | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== La vue character_detail ==== | ||
| + | |||
| + | |||
| + | Ouvrez maintenant le fichier '' | ||
| + | |||
| + | <code python> | ||
| + | from django.shortcuts import render, get_object_or_404, | ||
| + | from .forms import MoveForm | ||
| + | from .models import Character, Equipement | ||
| + | |||
| + | # Create your views here. | ||
| + | def character_list(request): | ||
| + | characters = Character.objects.filter() | ||
| + | return render(request, | ||
| + | |||
| + | def character_detail(request, | ||
| + | character = get_object_or_404(Character, | ||
| + | lieu = character.lieu | ||
| + | form=MoveForm() | ||
| + | return render(request, | ||
| + | ' | ||
| + | {' | ||
| + | </ | ||
| + | |||
| + | Afin de pouvoir créer un nouveau formulaire '' | ||
| + | |||
| + | |||
| + | |||
| + | |||
| + | ==== Template ==== | ||
| + | |||
| + | Nous avons à présent besoin de créer un fichier '' | ||
| + | |||
| + | - Nous avons besoin d' | ||
| + | - La ligne précédente va avoir besoin d' | ||
| + | - Nous avons besoin d'un bouton '' | ||
| + | - Enfin, nous devons ajouter '' | ||
| + | |||
| + | |||
| + | Ok, voyons maintenant à quoi devrait ressembler le HTML contenu dans le fichier '' | ||
| + | |||
| + | <code html> | ||
| + | {% extends ' | ||
| + | {% load static %} | ||
| + | {% block content %} | ||
| + | <div class=" | ||
| + | <h1> | ||
| + | <a href="/"> | ||
| + | </h1> | ||
| + | <form method=" | ||
| + | <b> Changer : </b> {{ form.as_ul }} | ||
| + | <button type=" | ||
| + | <a href=" | ||
| + | </ | ||
| + | </ | ||
| + | | ||
| + | |||
| + | {% endblock %} | ||
| + | </ | ||
| + | |||
| + | Rafraîchissons la page ! Et voilà : le formulaire s' | ||
| + | |||
| + | Mais attendez une minute! Lorsque vous sélectionnez une option, que se passera-t-il? | ||
| + | Rien! | ||
| + | Retournons à notre //vue//. | ||
| + | |||
| + | |||
| + | ==== Sauvegarder le contenu du formulaire ==== | ||
| + | |||
| + | Ouvrez à nouveau '' | ||
| + | |||
| + | <code python> | ||
| + | def character_detail(request, | ||
| + | character = get_object_or_404(Character, | ||
| + | form=MoveForm() | ||
| + | return render(request, | ||
| + | ' | ||
| + | {' | ||
| + | </ | ||
| + | |||
| + | |||
| + | Lorsque nous envoyons notre formulaire, nous revenons à la même vue. Cependant, nous récupérons les données dans '' | ||
| + | |||
| + | Donc dans notre //vue// nous avons deux situations différentes à gérer : la première quand on accède à la page pour la première fois et nous voulons un formulaire vide, et la seconde quand on revient à la //vue// avec les données que l& | ||
| + | |||
| + | |||
| + | <code python> | ||
| + | if request.method == " | ||
| + | [...] | ||
| + | else: | ||
| + | form = MoveForm() | ||
| + | </ | ||
| + | |||
| + | |||
| + | Il faut maintenant remplir à l' | ||
| + | </ | ||
| + | <code python> | ||
| + | form = MoveForm(request.POST, | ||
| + | </ | ||
| + | |||
| + | La prochaine étape est de vérifier que le formulaire a été rempli correctement (tous les champs obligatoires ont été remplis et aucune valeur incorrecte n& | ||
| + | |||
| + | Testons donc si notre formulaire est valide et, si c'est le cas, sauvegardons-le ! | ||
| + | |||
| + | <code python> | ||
| + | if form.is_valid(): | ||
| + | ancien_lieu = get_object_or_404(Equipement, | ||
| + | ancien_lieu.disponibilite = " | ||
| + | ancien_lieu.save() | ||
| + | form.save() | ||
| + | nouveau_lieu = get_object_or_404(Equipement, | ||
| + | nouveau_lieu.disponibilite = " | ||
| + | nouveau_lieu.save() | ||
| + | </ | ||
| + | |||
| + | |||
| + | En gros, nous effectuons deux choses ici : nous sauvegardons le nouvel état du personnage grâce à '' | ||
| + | |||
| + | Enfin, ce serait génial si nous pouvions tout de suite aller à la page '' | ||
| + | |||
| + | Maintenant, nous allons ajouter la ligne qui signifie & | ||
| + | |||
| + | <code python> | ||
| + | return redirect(' | ||
| + | </ | ||
| + | |||
| + | '' | ||
| + | |||
| + | Voyons à quoi ressemble maintenant notre //vue// ? | ||
| + | |||
| + | |||
| + | <code python> | ||
| + | def character_detail(request, | ||
| + | character = get_object_or_404(Character, | ||
| + | form=MoveForm() | ||
| + | if form.is_valid(): | ||
| + | ancien_lieu = get_object_or_404(Equipement, | ||
| + | ancien_lieu.disponibilite = " | ||
| + | ancien_lieu.save() | ||
| + | form.save() | ||
| + | nouveau_lieu = get_object_or_404(Equipement, | ||
| + | nouveau_lieu.disponibilite = " | ||
| + | nouveau_lieu.save() | ||
| + | return redirect(' | ||
| + | else: | ||
| + | form = MoveForm() | ||
| + | return render(request, | ||
| + | ' | ||
| + | {' | ||
| + | </ | ||
| + | |||
| + | Voyons si ça marche. Allez à l' | ||
| + | |||
| + | |||
| + | ==== Modèle complet ==== | ||
| + | |||
| + | Il ne reste plus qu'à raffiner le modèle afin qu'il corresponde aux contraintes définies en début d' | ||
| + | * Si le lieu de destination n'est pas libre, alors le changement ne doit pas être accepté. Il ne faut donc pas sauvegarder l' | ||
| + | <code python> | ||
| + | form.save(commit=False) | ||
| + | </ | ||
| + | * Avec cette option, le lieu est mis à jour dans l' | ||
| + | * Si c'est bon, alors effectuez les changements et n' | ||
| + | * Si ce n'est pas le cas, alors les changements ne doivent pas être enregistrés. | ||
| + | * N' | ||
| + | * Il est bien sûr possible de reprendre en l' | ||
| + | |||
| + | ==== Les messages ==== | ||
| + | |||
| + | Lorsqu' | ||
| + | |||
| + | <code html> | ||
| + | {% if message != '' | ||
| + | <div class=" | ||
| + | {{message}} | ||
| + | </ | ||
| + | {% endif %} | ||
| + | </ | ||
| + | |||
| + | |||
| + | |||
| + | Et normalement c'est tout ! Félicitations ! :) | ||