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:12] – edauce | public:appro-s7:td_web_hamsters [2024/11/02 17:03] (Version actuelle) – [Indications] edauce |
---|
Vous pouvez bien sûr conserver la structure de base qui est d'avoir un ensemble de créatures et/ou de personnages, et un ensemble de lieux avec des fonctions différentes (par exemple, pour un centre d'entrainement : terrain de foot, cantine, salle de muscu, dortoir). Il peut y avoir des variantes : Pour une maison des poupées il peut y avoir plusieurs chambres, une pièce commune, un jardin et une terrasse. Laissez libre cours à votre imagination. | Vous pouvez bien sûr conserver la structure de base qui est d'avoir un ensemble de créatures et/ou de personnages, et un ensemble de lieux avec des fonctions différentes (par exemple, pour un centre d'entrainement : terrain de foot, cantine, salle de muscu, dortoir). Il peut y avoir des variantes : Pour une maison des poupées il peut y avoir plusieurs chambres, une pièce commune, un jardin et une terrasse. Laissez libre cours à votre imagination. |
| |
Les créatures passent par différents états au cours de la journée en fonction des lieux qu'ils visitent. | Les personnages passent par différents états au cours de la journée en fonction des lieux qu'ils visitent. |
| |
<note tip> ** Rappel ** | <note tip> ** Rappel ** |
| |
Reprenez cette structure de données de type ''Animal'' -- ''Equipement'' utilisée dans les TD précédents | Reprenez cette structure de données de type ''Personnage'' -- ''Equipement'' utilisée dans les TD précédents |
{{ :public:appro-s7:mie-_ea.png?600| }} | {{ :public:appro-s7:mie-_ea_-_projet_1_.png?600 |}} |
</note> | </note> |
| |
| |
==== Indications ==== | ==== Indications ==== |
Créez un projet 'petland' et reprenez toutes les étapes 1 à 15 du tutoriel [[public:appro-s7:td_web|précédent]] avec le modèle suivant, en remplaçcant "Animal" par "Character" pour être plus général. | Créez un projet 'playground' et reprenez toutes les étapes 1 à 15 du tutoriel [[public:appro-s7:td_web|précédent]] avec le modèle suivant, en remplaçcant "Animal" par "Character" pour être plus général. |
| |
=== model.py === | === model.py === |
| |
class Character(models.Model): | class Character(models.Model): |
id_char = models.CharField(max_length=100, primary_key=True) | id_character = models.CharField(max_length=100, primary_key=True) |
etat = models.CharField(max_length=20) | etat = models.CharField(max_length=20) |
type = models.CharField(max_length=20) | type = models.CharField(max_length=20) |
race = models.CharField(max_length=20) | team = models.CharField(max_length=20) |
photo = models.CharField(max_length=200) | photo = models.CharField(max_length=200) |
lieu = models.ForeignKey(Equipement, on_delete=models.CASCADE) | lieu = models.ForeignKey(Equipement, on_delete=models.CASCADE) |
def __str__(self): | def __str__(self): |
return self.id_animal | return self.id_character |
</code> | </code> |
| |
| |
Vous deviez obtenir une interface simple de ce type: | Vous deviez obtenir une interface simple de ce type: |
| |
{{ :public:appro-s7:simple-hamster.png?600 |}} | {{ :public:appro-s7:simple-hamster.png?600 |}} |
| |
Vous pouvez exploiter les photos qui sont définies dans les attributs du modèle pour obtenir par exemple: | Vous pouvez exploiter les photos qui sont définies dans les attributs du modèle pour obtenir par exemple: |
| |
{{ :public:appro-s7:screenshot.png?500 |}} | {{ :public:appro-s7:animalerie_web.png?800 |}} |
| |
==== Formulaires Django ==== | ==== Formulaires Django ==== |
(repris du tutoriel {{https://tutorial.djangogirls.org/fr/django_forms/}}) | (repris du tutoriel {{https://tutorial.djangogirls.org/fr/django_forms/}}) |
| |
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 animaux. Les formulaires (forms) vont nous permettre de rendre le site dynamique ! | 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 : ''forms.py''. | Comme toutes les choses importantes dans Django, les formulaires ont leur propre fichier : ''forms.py''. |
Nous allons devoir créer un fichier avec ce nom dans notre dossier blog. | Nous allons devoir créer un fichier avec ce nom dans notre dossier blog. |
| |
petland | playground |
└── forms.py | └── forms.py |
| |
from django import forms | from django import forms |
| |
from .models import Animal | from .models import Character |
| |
class MoveForm(forms.ModelForm): | class MoveForm(forms.ModelForm): |
| |
class Meta: | class Meta: |
model = Animal | model = Character |
fields = ('lieu',) | fields = ('lieu',) |
</code> | </code> |
<html> | Tout d'abord, nous avons besoin d'importer les formulaires Django (''from django import forms''), puis notre modèle Character (''from .models import Character''). |
<p>Tout d'abord, nous avons besoin d'importer les formulaires Django (<code>from django import forms</code>), puis notre modèle <code>Animal</code> (<code>from .models import Animal</code>).</p> | |
<p>Comme vous l'avez probablement deviné, <code>MoveForm</code> est le nom de notre formulaire. Nous avons besoin d'indiquer à Django que ce formulaire est un <code>ModelForm</code> (pour que Django fasse certaines choses automatiquement pour nous). Pour cela, nous utilisons <code>forms.ModelForm</code>.</p> | Comme vous l'avez probablement deviné, ''MoveForm'' est le nom de notre formulaire. Nous avons besoin d'indiquer à Django que ce formulaire est un ModelForm (pour que Django fasse certaines choses automatiquement pour nous). Pour cela, nous utilisons ''forms.ModelForm''. |
<p>Ensuite, nous avons la <code>class Meta</code> qui nous permet de dire à Django quel modèle il doit utiliser pour créer ce formulaire (<code>model = Animal</code>).</p> | |
<p>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 <code>lieu</code> apparaisse dans notre formulaire. </p> | Ensuite, nous avons la class Meta qui nous permet de dire à Django quel modèle il doit utiliser pour créer ce formulaire (''model = Character''). |
<p>Et voilà, c'est tout ! Tout ce qu'il nous reste à faire, c'est d'utiliser ce formulaire dans une <em>vue</em> et de l'afficher dans un template.</p> | |
<p>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.</p> | 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. |
</html> | |
| Et voilà, c'est tout ! Tout ce qu'il nous reste à faire, c'est d'utiliser ce formulaire dans une vue et de l'afficher dans un template. |
| |
| 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 ==== | ==== Lien vers une page contenant le formulaire ==== |
| |
Il est temps d'ouvrir petland/templates/petland/base.html dans l'éditeur de code et ajouter un lien vers la vue ''animal_detail''. | Il est temps d'ouvrir ''playground/templates/playground/base.html'' dans l'éditeur de code et ajouter un lien vers la vue ''character_detail''. |
<code html> | <code html> |
<a href="{% url 'animal_detail' id_animal=animal.id_animal %}">{{ animal.id_animal }}</a> | <a href="{% url 'character_detail' id_character=character.id_character %}">{{ character.id_character }}</a> |
</code> | </code> |
| |
| |
==== URL ==== | ==== URL ==== |
Ouvrez le fichier <code>petland/urls.py</code> dans l'éditeur de code et mettez ceci: | Ouvrez le fichier <code>playground/urls.py</code> dans l'éditeur de code et mettez ceci: |
<code python> | <code python> |
from django.urls import path | from django.urls import path |
| |
urlpatterns = [ | urlpatterns = [ |
path('', views.animal_list, name='animal_list'), | path('', views.character_list, name='character_list'), |
path('animal/<str:id_animal>/', views.animal_detail, name='animal_detail'), | path('character/<str:id_character>/', views.character_detail, name='character_detail'), |
path('animal/<str:id_animal>/?<str:message>', views.animal_detail, name='animal_detail_mes'), | path('character/<str:id_character>/?<str:message>', views.character_detail, name='character_detail_mes'), |
] | ] |
</code> | </code> |
| |
| |
==== La vue animal_detail ==== | ==== La vue character_detail ==== |
| |
| |
| Ouvrez maintenant le fichier ''playground/views.py'' dans l'éditeur de code et ajoutez les lignes suivantes avec celles du ''from'' qui existent déjà : |
| |
<html> | |
<p>Ouvrez maintenant le fichier <code>petland/views.py</code> dans l'éditeur de code et ajoutez les lignes suivantes avec celles du <code>from</code> qui existent déjà :</p> | |
</html> | |
<code python> | <code python> |
from django.shortcuts import render, get_object_or_404, redirect | from django.shortcuts import render, get_object_or_404, redirect |
from .forms import MoveForm | from .forms import MoveForm |
from .models import Animal, Equipement | from .models import Character, Equipement |
| |
# Create your views here. | # Create your views here. |
def animal_list(request): | def character_list(request): |
animals = Animal.objects.filter() | characters = Character.objects.filter() |
return render(request, 'petland/pet_list.html', {'animals': animals}) | return render(request, 'playground/character_list.html', {'characters': characters}) |
| |
def animal_detail(request, id_animal): | def character_detail(request, id_character): |
animal = get_object_or_404(Animal, id_animal=id_animal) | character = get_object_or_404(Character, id_character=id_character) |
lieu = animal.lieu | lieu = character.lieu |
form=MoveForm() | form=MoveForm() |
return render(request, | return render(request, |
'petland/animal_detail.html', | 'playground/character_detail.html', |
{'animal': animal, 'lieu': lieu, 'form': form}) | {'character': character, 'lieu': lieu, 'form': form}) |
</code> | </code> |
<html> | |
| |
<p>Afin de pouvoir créer un nouveau formulaire <code>Move</code>, nous avons besoin d'appeler la fonction <code>MoveForm()</code> et de la passer au template. Nous reviendrons modifier cette <em>vue</em> plus tard, mais pour l'instant, créons rapidement un template pour ce formulaire.</p> | Afin de pouvoir créer un nouveau formulaire ''Move'', nous avons besoin d'appeler la fonction ''MoveForm()'' et de la passer au template. Nous reviendrons modifier cette //vue// plus tard, mais pour l'instant, créons rapidement un template pour ce formulaire. |
| |
</html> | |
| |
| |
==== Template ==== | ==== Template ==== |
| |
<html> | Nous avons à présent besoin de créer un fichier ''character_detail.html'' dans le dossier ''playground/templates/playground'' et de l'ouvrir dans l'éditeur de code. Afin que notre formulaire fonctionne, nous avons besoin de plusieurs choses : |
<p>Nous avons à présent besoin de créer un fichier <code>animal_detail.html</code> dans le dossier <code>petland/templates/animalerie</code> et de l'ouvrir dans l'éditeur de code. Afin que notre formulaire fonctionne, nous avons besoin de plusieurs choses :</p> | |
<ul> | - Nous avons besoin d'afficher le formulaire. Pour cela, nous n'avons qu'à utiliser ''{{ form.as_uk }}''. |
<li>Nous avons besoin d'afficher le formulaire. Pour cela, nous n'avons qu'à utiliser <code>{{ form.as_uk }}</code>.</li> | - La ligne précédente va avoir besoin d'être entourée des balises HTML ''<form method="POST">...</form>''. |
<li>La ligne précédente va avoir besoin d'être entourée des balises HTML <code><form method="POST">...</form></code>.</li> | - Nous avons besoin d'un bouton ''Valider''. Nous allons le créer à l'aide d'un bouton HTML : ''<button type="submit">Valider</button>''. |
<li>Nous avons besoin d'un bouton <code>Valider</code>. Nous allons le créer à l'aide d'un bouton HTML : <code><button type="submit">Valider</button></code>.</li> | - Enfin, nous devons ajouter ''{% csrf_token %}'' juste après ''<form ...>''. C'est très important car c'est ce qui va permettre de sécuriser votre formulaire ! Si vous oubliez ce détail, Django se plaindra lorsque vous essaierez de sauvegarder le formulaire: |
<li>Enfin, nous devons ajouter <code>{% csrf_token %}</code> juste après <code><form ...></code>. C'est très important car c'est ce qui va permettre de sécuriser votre formulaire ! Si vous oubliez ce détail, Django se plaindra lorsque vous essaierez de sauvegarder le formulaire:</li> | |
</ul> | |
<p><img src="images/csrf2.png" alt="CSFR Forbidden page"></p> | Ok, voyons maintenant à quoi devrait ressembler le HTML contenu dans le fichier ''character_detail.html'' : |
<p>Ok, voyons maintenant à quoi devrait ressembler le HTML contenu dans le fichier <code>animal_detail.html</code> : | |
</html> | |
<code html> | <code html> |
{% extends 'animalerie/base.html' %} | {% extends 'playground/base.html' %} |
{% load static %} | {% load static %} |
{% block content %} | {% block content %} |
<div class="page-header"> | <div class="page-header"> |
<h1> | <h1> |
<a href="/">{{ animal.id_animal }}</a> | <a href="/">{{ character.id_character }}</a> |
</h1> | </h1> |
<form method="POST" class="post-form">{% csrf_token %} | <form method="POST" class="post-form">{% csrf_token %} |
<b> Changer : </b> {{ form.as_ul }} | <b> Changer : </b> {{ form.as_ul }} |
<button type="submit" class="btn btn-outline-light">OK</button> | <button type="submit" class="btn btn-outline-light">OK</button> |
<a href="{% url 'animal_list' %}">Back</a> | <a href="{% url 'character_list' %}">Back</a> |
</form> | </form> |
</div> | </div> |
{% endblock %} | {% endblock %} |
</code> | </code> |
<html> | |
<p>Rafraîchissons la page ! Et voilà : le formulaire s'affiche sous la forme d'une liste d'options!</p> | Rafraîchissons la page ! Et voilà : le formulaire s'affiche sous la forme d'une liste d'options! |
<p>Mais attendez une minute! Lorsque vous sélectionnez une option, que se passera-t-il?</p> | |
| Mais attendez une minute! Lorsque vous sélectionnez une option, que se passera-t-il? |
Rien! | Rien! |
Retournons à notre <em>vue</em>.</p> | Retournons à notre //vue//. |
</html> | |
| |
==== Sauvegarder le contenu du formulaire ==== | ==== Sauvegarder le contenu du formulaire ==== |
<html> | |
<p>Ouvrez à nouveau <code>blog/views.py</code> dans l'éditeur de code. Actuellement, <code>post_new</code> n'est composé que des lignes de code suivantes :</p> | Ouvrez à nouveau ''blog/views.py'' dans l'éditeur de code. Actuellement, ''post_new'' n'est composé que des lignes de code suivantes : |
</html> | |
<code python> | <code python> |
def animal_detail(request, id_animal): | def character_detail(request, id_character): |
animal = get_object_or_404(Animal, id_animal=id_animal) | character = get_object_or_404(Character, id_character=id_character) |
form=MoveForm() | form=MoveForm() |
return render(request, | return render(request, |
'animalerie/animal_detail.html', | 'playground/character_detail.html', |
{'animal': animal, 'lieu': lieu, 'form': form}) | {'character': character, 'lieu': lieu, 'form': form}) |
</code> | </code> |
| |
<html> | |
<p>Lorsque nous envoyons notre formulaire, nous revenons à la même vue. Cependant, nous récupérons les données dans <code>request</code>, et plus particulièrement dans <code>request.POST</code>. Vous rappelez-vous comment dans le fichier HTML, notre définition de la variable <code><form></code> avait la méthode <code>method="POST"</code>? Tous les champs du formulaire se trouvent maintenant dans <code>request.POST</code>. Veillez à ne pas renommer <code>POST</code> en quoi que ce soit d'autre : la seule autre valeur autorisée pour <code>method</code> est <code>GET</code>. Malheureusement, nous n'avons pas le temps de rentrer dans les détails aujourd'hui.</p> | Lorsque nous envoyons notre formulaire, nous revenons à la même vue. Cependant, nous récupérons les données dans ''request'', et plus particulièrement dans ''request.POST''. Vous rappelez-vous comment dans le fichier HTML, notre définition de la variable ''form'' avait la méthode ''method=POST''? Tous les champs du formulaire se trouvent maintenant dans ''request.POST''. Veillez à ne pas renommer ''POST'' en quoi que ce soit d'autre : la seule autre valeur autorisée pour ''method'' est ''GET''. Malheureusement, nous n'avons pas le temps de rentrer dans les détails aujourd'hui. |
<p>Donc dans notre <em>vue</em> 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 <em>vue</em> avec les données que l'on a saisies dans le formulaire. Pour gérer ces deux cas, nous allons utiliser une condition | |
</html> | 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'on a saisies dans le formulaire. Pour gérer ces deux cas, nous allons utiliser une condition |
| |
<code python> | <code python> |
</code> | </code> |
| |
<html> | |
<p>Il faut maintenant remplir à l'endroit des pointillés <code>[...]</code>. Si <code>method</code> contient <code>POST</code> alors on veut construire le <code>MoveForm</code> avec les données du formulaire, n'est-ce pas ? Nous allons le faire comme cela : | Il faut maintenant remplir à l'endroit des pointillés ''[...]''. Si ''method'' contient ''POST'' alors on veut construire le ''MoveForm'' avec les données du formulaire, n'est-ce pas ? Nous allons le faire comme cela : |
</html> | </html> |
<code python> | <code python> |
form = MoveForm(request.POST, instance=animal) | form = MoveForm(request.POST, instance=character) |
</code> | </code> |
<html> | |
<p>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'a été envoyée). Nous allons faire ça en utilisant <code>form.is_valid()</code>.</p> | 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'a été envoyée). Nous allons faire ça en utilisant ''form.is_valid()''. |
<p>Testons donc si notre formulaire est valide et, si c'est le cas, sauvegardons-le !</p> | |
</html> | Testons donc si notre formulaire est valide et, si c'est le cas, sauvegardons-le ! |
<code python> | <code python> |
if form.is_valid(): | if form.is_valid(): |
ancien_lieu = get_object_or_404(Equipement, id_equip=animal.lieu.id_equip) | ancien_lieu = get_object_or_404(Equipement, id_equip=character.lieu.id_equip) |
ancien_lieu.disponibilite = "libre" | ancien_lieu.disponibilite = "libre" |
ancien_lieu.save() | ancien_lieu.save() |
form.save() | form.save() |
nouveau_lieu = get_object_or_404(Equipement, id_equip=animal.lieu.id_equip) | nouveau_lieu = get_object_or_404(Equipement, id_equip=character.lieu.id_equip) |
nouveau_lieu.disponibilite = "occupé" | nouveau_lieu.disponibilite = "occupé" |
nouveau_lieu.save() | nouveau_lieu.save() |
</code> | </code> |
| |
<html> | |
<p>En gros, nous effectuons deux choses ici : nous sauvegardons le nouvel état de l'animal grâce à <code>form.save</code> et nous mettons à jour l'occupation des lieux. Rappelez vous, tout déplacement d'animal s'acccompagne d'un changement d'occupation. Nous devons également modifier les lieux. <code>ancien_lieu.save()</code> et <code>nouveau_lieu.save()</code> sauvegarderont les changements. Et voilà, la mise à jour est enregistrée !</p> | |
<p>Enfin, ce serait génial si nous pouvions tout de suite aller à la page <code>animal_detail</code> avec le contenu que nous venons de créer. Pour cela, nous avons besoin d'importer une dernière chose : | |
| |
<p>Maintenant, nous allons ajouter la ligne qui signifie "aller à la page <code>animal_detail</code> pour le changement qui vient d'être enregistré</p> | En gros, nous effectuons deux choses ici : nous sauvegardons le nouvel état du personnage grâce à ''form.save'' et nous mettons à jour l'occupation des lieux. Rappelez vous, tout déplacement du personnage s'acccompagne d'un changement d'occupation. Nous devons également modifier les lieux. ''ancien_lieu.save()'' et ''nouveau_lieu.save()'' sauvegarderont les changements. Et voilà, la mise à jour est enregistrée ! |
</html> | |
| Enfin, ce serait génial si nous pouvions tout de suite aller à la page ''character_detail'' avec le contenu que nous venons de créer. Pour cela, nous avons besoin d'importer une dernière chose : |
| |
| Maintenant, nous allons ajouter la ligne qui signifie "aller à la page ''character_detail'' pour le changement qui vient d'être enregistré. |
<code python> | <code python> |
return redirect('animal_detail', id_animal=id_animal) | return redirect('character_detail', id_character=id_character) |
</code> | </code> |
<html> | |
<p><code>animal_detail</code> est le nom de la vue où nous voulons aller. | |
| |
<p>Voyons à quoi ressemble maintenant notre <em>vue</em> ?</p> | ''character_detail'' est le nom de la vue où nous voulons aller. |
</html> | |
| Voyons à quoi ressemble maintenant notre //vue// ? |
| |
<code python> | <code python> |
def animal_detail(request, id_animal): | def character_detail(request, id_character): |
animal = get_object_or_404(Animal, id_animal=id_animal) | character = get_object_or_404(Character, id_character=id_character) |
form=MoveForm() | form=MoveForm() |
if form.is_valid(): | if form.is_valid(): |
ancien_lieu = get_object_or_404(Equipement, id_equip=animal.lieu.id_equip) | ancien_lieu = get_object_or_404(Equipement, id_equip=character.lieu.id_equip) |
ancien_lieu.disponibilite = "libre" | ancien_lieu.disponibilite = "libre" |
ancien_lieu.save() | ancien_lieu.save() |
form.save() | form.save() |
nouveau_lieu = get_object_or_404(Equipement, id_equip=animal.lieu.id_equip) | nouveau_lieu = get_object_or_404(Equipement, id_equip=character.lieu.id_equip) |
nouveau_lieu.disponibilite = "occupé" | nouveau_lieu.disponibilite = "occupé" |
nouveau_lieu.save() | nouveau_lieu.save() |
return redirect('animal_detail', id_animal=id_animal) | return redirect('character_detail', id_character=id_character) |
else: | else: |
form = MoveForm() | form = MoveForm() |
return render(request, | return render(request, |
'animalerie/animal_detail.html', | 'playground/character_detail.html', |
{'animal': animal, 'lieu': lieu, 'form': form}) | {'character': character, 'lieu': lieu, 'form': form}) |
</code> | </code> |
<html> | |
<p>Voyons si ça marche. Allez à l'adresse <a href="http://127.0.0.1:8000/animal/Tic/" target="_blank">http://127.0.0.1:8000/animal/Tic/</a>, selectionnez un nouveau lieu, sauvegardez ... et voilà ! La mise a jour est prise en compte !</p> | Voyons si ça marche. Allez à l'adresse ''http://127.0.0.1:8000/character/Tic/'', selectionnez un nouveau lieu, sauvegardez ... et voilà ! La mise a jour est prise en compte ! |
</html> | |
| |
==== Modèle complet ==== | ==== Modèle complet ==== |
| |
Il ne reste plus qu'à raffiner le modèle afin qu'il corresponde aux contraintes définies en début d'énoncé. | Il ne reste plus qu'à raffiner le modèle afin qu'il corresponde aux contraintes définies en début d'énoncé. |
* Si le lieu de destination n'est pas libre, alors le changement ne doit pas être accepté. Il ne faut donc pas sauvegarder l'état de l'animal immédiatement. Cela est possible grâce à l'option : | * Si le lieu de destination n'est pas libre, alors le changement ne doit pas être accepté. Il ne faut donc pas sauvegarder l'état du personnage immédiatement. Cela est possible grâce à l'option : |
<code python> | <code python> |
form.save(commit=False) | form.save(commit=False) |
</code> | </code> |
* Avec cette option, le lieu est mis à jour dans l'objet ''animal'' mais pas dans la base de données! Il est alors possible de tester si le nouveau lieu est bien libre en regardant si ''animal.lieu.disponibilite'' est ''"libre"''. | * Avec cette option, le lieu est mis à jour dans l'objet ''character'' mais pas dans la base de données! Il est alors possible de tester si le nouveau lieu est bien libre en regardant si ''character.lieu.disponibilite'' est ''"libre"''. |
* Si c'est bon, alors effectuez les changements et n'oubliez pas de sauvegarder avec ''animal.save()''. | * Si c'est bon, alors effectuez les changements et n'oubliez pas de sauvegarder avec ''character.save()''. |
* Si ce n'est pas le cas, alors les changements ne doivent pas être enregistrés. | * Si ce n'est pas le cas, alors les changements ne doivent pas être enregistrés. |
* N'oubliez pas non plus: le changement de lieu a pour conséquence un changement d'état, qui passe par exemple d'''"affamé"'' à ''"repus"'' lorsqu'on le déplace sur la mangeoire. Reprenez toutes les conditions et tenez en compte pour la mise à jour de l'animal. | * N'oubliez pas non plus: le changement de lieu a pour conséquence un changement d'état, qui passe par exemple d'''"affamé"'' à ''"repus"'' lorsqu'on le déplace sur la mangeoire. Reprenez toutes les conditions et tenez en compte pour la mise à jour du personnage. |
* Il est bien sûr possible de reprendre en l'adaptant la structure de contrôleur vue au TD1. | * Il est bien sûr possible de reprendre en l'adaptant la structure de contrôleur vue au TD1. |
| |
==== Les messages ==== | ==== Les messages ==== |
| |
Lorsqu'un changement n'est pas autorisé, il est préférable d'afficher un message d'avertissement. Le message transmis comme paramètre au template ''animal_detail.html''. Le cadre sera activé uniquement si le message est non vide. Pensez à modifier les paramètres d'appel du template dans ''views.py''. | Lorsqu'un changement n'est pas autorisé, il est préférable d'afficher un message d'avertissement. Le message transmis comme paramètre au template ''character_detail.html''. Le cadre sera activé uniquement si le message est non vide. Pensez à modifier les paramètres d'appel du template dans ''views.py''. |
| |
<code html> | <code html> |
</code> | </code> |
| |
==== Encore un petit effort : déployons ! ==== | |
<html> | |
<p>Nos modifications fonctionnent-elles sur PythonAnywhere ? Pour le savoir, déployons à nouveau !</p> | |
<ul> | |
<li>Tout d'abord, commitez votre nouveau code et pushez le à nouveau sur GitHub:</li> | |
</ul> | |
<p></p><p class="code-label">command-line</p><p></p> | |
<pre><code>$ git status | |
$ git add . | |
$ git status | |
$ git commit -m "Added views to create/edit blog post inside the site." | |
$ git pus | |
</code></pre><ul> | |
<li>Puis, dans la console bash de <a href="https://www.pythonanywhere.com/consoles/" target="_blank">PythonAnywhere</a>:</li> | |
</ul> | |
<p></p><p class="code-label">Ligne de commande PythonAnywhere</p><p></p> | |
<pre><code>$ cd ~/<your-pythonanywhere-domain>.pythonanywhere.com | |
$ git pull | |
[...] | |
</code></pre><p>(N’oubliez pas de remplacer <code><your-pythonanywhere-domain></code> avec votre propre sous-domaine PythonAnywhere, sans les chevrons.)</p> | |
<ul> | |
<li>Enfin, allez sur <a href="https://www.pythonanywhere.com/web_app_setup/" target="_blank">"Web" page</a> (utilisez le bouton de menu en haut à droite de la console) et cliquez <strong>Reload</strong>. Actualisez votre blog <a href="https://subdomain.pythonanywhere.com" target="_blank">https://subdomain.pythonanywhere.com</a> pour voir les changements.</li> | |
</ul> | |
<p>Et normalement c'est tout ! Félicitations ! :)</p> | |
| |
| |
</section> | Et normalement c'est tout ! Félicitations ! :) |
</html> | |