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:51] – [Template] 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> |
| |
| |
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_char | 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 ==== |
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. | 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> | |
| |
| |
- 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: | - 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: |
| |
{{images/csrf2.png|alt=CSFR Forbidden page}} | |
| |
Ok, voyons maintenant à quoi devrait ressembler le HTML contenu dans le fichier ''character_detail.html'' : | Ok, voyons maintenant à quoi devrait ressembler le HTML contenu dans le fichier ''character_detail.html'' : |
Mais attendez une minute! Lorsque vous sélectionnez une option, que se passera-t-il? | Mais attendez une minute! Lorsque vous sélectionnez une option, que se passera-t-il? |
Rien! | Rien! |
Retournons à notre /vue//. | Retournons à notre //vue//. |
| |
| |
==== 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 character_detail(request, id_character): | def character_detail(request, id_character): |
</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=character) | 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(): |
</code> | </code> |
| |
<html> | |
<p>En gros, nous effectuons deux choses ici : nous sauvegardons le nouvel état du personnage grâce à <code>form.save</code> 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. <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>character_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>character_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('character_detail', id_character=id_character) | return redirect('character_detail', id_character=id_character) |
</code> | </code> |
<html> | |
<p><code>character_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> |
{'character': character, '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/character/Tic/" target="_blank">http://127.0.0.1:8000/character/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 ==== |
</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> | |