• 8 heures
  • Moyenne

Ce cours est visible gratuitement en ligne.

course.header.alt.is_video

course.header.alt.is_certifying

J'ai tout compris !

Mis à jour le 01/02/2019

Affichez le contenu d'un template

Connectez-vous ou inscrivez-vous gratuitement pour bénéficier de toutes les fonctionnalités de ce cours !

Notre page d'accueil est assez vide, n'est-ce pas ? C'est le moment d'afficher le contenu d'index.html ! 

Comprendre l'architecture modèle / vue / template

La structure d'un projet est une des clés qui garantit sa bonne évolution, exactement comme dans votre ordinateur ! Imaginez que vous repreniez le projet d'une autre personne, ou que vous ouvriez le vôtre dans six mois. Vous ne voulez pas perdre de temps à chercher comment il est organisé ! Vous voulez aller droit au but et apporter votre modification sans pour autant tout casser.

C'est pourquoi la plupart des frameworks pensés pour le web choisissent de séparer les fichiers dans plusieurs dossiers distincts. Cela peut paraître un peu contraignant au début mais ce sont de bonnes pratiques qui garantissent la bonne évolution de votre projet.

Flask, comme vous le savez désormais, n'impose pas vraiment de structure, il la propose. S'inspirant du modèle MVC (Modèle / Vue / Contrôleur) de bien des frameworks, il se base sur trois piliers fortement imbriqués : le modèle, la vue et le template. Voyons-les en détail.

Le Modèle

Définition

Un modèle, comme nous l'avons vu dans le chapitre précédent, représente la structure de l'objet qui sera stocké dans la base de données.

Dans Flask, le modèle de chaque objet est représenté par une classe dans le fichier models.py. La classe hérite de db.Model et peut donc utiliser les méthodes de la classe parent.

Deux parties sont à distinguer dans un modèle :

  • la structure de l'item dans la base de données,

  • les attributs d'instance exposés. 

L'appel à db.Column crée une nouvelle colonne dans la table. Cela permet de filtrer les résultats d'une recherche par le contenu de cette colonne, par exemple, en utilisant la méthode TableName.query.filter_by(column_name=filter).first().

La méthode __init__, elle, construit l'instance. Chaque attribut exposé à cet endroit pourra être modifié par la suite de la même manière que n'importe quelle instance de classe Python. Dans notre exemple, vous pouvez ainsi créer un nouvel élément content dans la base en spécifiant sa description et son genre mais pas son id.

Exemple

Dans notre projet, models.py contient un modèle Content. Pour comprendre la différence entre ce qui est stocké en base et les valeurs retournées, je vous propose d'améliorer la gestion de l'attribut gender.

Pour l'instant, nous enregistrons le genre en tant qu'entier mais nous ne connaissons pas (encore) le chiffre associé à chacun.

Nous verrons plus tard que Facebook renvoie les valeurs male ou female de l'utilisateur connecté. Il serait donc intéressant de pouvoir associer chaque chaîne de caractères à un nombre.

Créons une nouvelle classe, Gender, qui héritera de enum :

models.py

import enum

class Gender(enum.Enum):
    female = 0
    male = 1
    other = 2
    ...

À présent, modifiez la valeur de la colonne gender et l'initialisation de la base :

models.py

class Content(db.Model):
    gender = db.Column(db.Enum(Gender), nullable=False)

def init_db():
    db.session.add(Content("THIS IS SPARTAAAAAAA!!!", Gender['male']))
    db.session.add(Content("What's your favorite scary movie?", Gender['female']))

Cela vous permet de créer des instances de cette manière : Content('Personne ne te faisait pitié, ni sur le moment, ni après, on était absolument sans défense devant toi.', Gender['male']).

Vous pourrez ensuite les retrouver de la manière suivante :   Content.query.filter_by(gender=Gender['male'])

Le template

Un template est un fichier HTML qui peut recevoir des objets Python et qui est lié à une vue (nous y reviendrons). Il est placé dans le dossier templates.

Concrètement, un template peut interpréter des variables et les afficher. Par exemple, nous pouvons "donner" la variable tom="Tom" au template index.html et ce dernier l'affichera à la place du prénom.

La vue

Un rôle essentiel

Les vues contenues dans le fichier views.py jouent un rôle primordial : elles décident du contenu à afficher sur une page. Plus spécifiquement, ce sont elles qui génèrent le contenu à renvoyer aux requêtes qui leur sont adressées.

Une vue est une fonction qui renvoie une réponse à une requête HTTP. Toute fonction décorée par @app.route est une vue.

On appelle route l'URL à laquelle va répondre la vue. Par exemple : /index.

Afin de bien comprendre le rôle majeur des vues, intéressons-nous au cheminement d'une requête.

  • L'utilisateur tape http://le-test-ultime.hello-birds.com dans son navigateur puis appuie sur entrée. Cela génère une requête HTTP de cette forme :

GET/HTTP/1.1
Host:le-test-ultime.hello-birds.com
  • Le serveur à l'adresse le-test-ultime.hello-birds.com reçoit la requête HTTP. Il cherche dans les vues la route correspondant à la requête en fonction de la méthode HTTP utilisée et de l'URL.

  • Le serveur exécute la vue : éventuellement, si la route contient des paramètres, ils sont passés comme arguments à la vue. Si une modification d'un objet en base de données est demandée, la vue fait appel au modèle. Si un template est demandé, la vue l'appelle.

  • Le serveur transmet la réponse HTTP de la vue au navigateur de l'utilisateur (appelé communément client).

Exemple

Afin de mettre en pratique ce que nous venons d'explorer, affichons le contenu du template index.html lorsque l'utilisateur arrive sur la page d'accueil.

views.py

from flask import Flask, render_template

...

@app.route('/')
def index():
    return render_template('index.html')

Pourquoi ajouter un slash à la fin de l'URL ?

Les utilisateurs peuvent taper deux adresses différentes  /index ou  /index/. Hé oui, ce ne sont pas les mêmes ! Si vous déclarez une route sans le slash final (/index), le serveur renverra une erreur 404 (page non trouvée) si l'utilisateur tape  /index/ . Mais si vous déclarez une route avec le slash final (/index/) et que l'utilisateur tape  /index , le serveur ne renverra pas d'erreur. Pensez-y ! :)

Le nom de vos routes doit être parlant ! Vous et l'utilisateur devez être en mesure de comprendre, en lisant l'URL, l'action qui sera effectuée. Par exemple, évitez d'utiliser une route qui aurait cette structure : /mise_a_jour_description_1 . Préférez l'url suivante : /contents/1/update.

Il s'agit d'ailleurs d'une des bonnes pratiques les plus importantes à respecter lorsque l'on crée une application web : l'interface uniforme de l'architecture REST.

REST : dénominations conseillées des routes

REST est un acronyme pour Representational State Transfer. Cette architecture impose six contraintes que vous pouvez choisir de respecter :

  • Séparation client / serveur

  • Stateless (sans état)

  • Cacheable (cachable)

  • Layered system (système à plusieurs couches)

  • Uniform interface (interface uniforme)

  • Code on demand

Comment appliquer REST dans un projet Flask ? La question demanderait un cours entier ! Intéressez-vous en premier à l'interface uniforme et prenez le temps de bien comprendre comment créer de bonnes URL.

Prenez le temps de lire le chapitre Une architecture, pas un protocole du cours Construisez une API REST avec Symphony de Sarah Khalil.

Je vous retrouve au chapitre suivant pour améliorer le template !

Code du chapitre

Retrouvez le code de ce chapitre à cette adresse.

Exemple de certificat de réussite
Exemple de certificat de réussite