La propreté et la structure du code de l'application compte pour 5 points dans la note finale. Plusieurs normes et règles sont à respecter.
Que ce soit dans une route Flask, une classe d'un modèle SQLAlchemy, un template, du Javascript, etc., tout doit être commenté pour je puisse voir ce que telles lignes de code font et si vous avez compris votre propre code. Le commentaire de code est essentiel, pas seulement pour ce devoir: un code commenté est compréhensible par tous, et modifiable par tous.
Exemple de commentaires pour différents langages:
# itération sur la liste des pays et affichage des pays un à un
for un_pays in pays:
print(pays)
// affichage de la variable i
console.log(i);
/* les balises span sont bleues */
span {
color: blue;
}
<!-- Ceci est un paragraphe -->
<p>Un paragraphe</p>
-- sélection de tous les pays
SELECT *
FROM country a -- a est l'alias de country dans cette requête
Pour Python, un autre type de commentaire doit être présent: il s'agit de la documentation des classes et des fonctions, donc chaque fois qu'il y a un class
ou un def
dans le code. Prenons deux exemples:
models/users.py
avec ses attributs et ses méthodesclass Users(UserMixin, db.Model):
"""
Une classe représentant les utilisateurs. On indique ici une rapide description de la classe.
Attributes
----------
id : sqlalchemy.sql.schema.Column
Identifiant de l'utilisateur. C'est la clé primaire. Cet attribut est une Column SQLALchemy.
prenom : sqlalchemy.sql.schema.Column
Prénom de l'utilisateur
password : sqlalchemy.sql.schema.Column
Mot de passé hashé de l'utilisateur
mail : sqlalchemy.sql.schema.Column
Adresse mail de l'utilisateur
Methods
-------
identification(mail, password)
Permet l'identification d'un utilisateur à partir d'un mail et d'un mot de passe fournis
"""
__tablename__ = "users"
id = db.Column(db.Integer, unique=True, nullable=False, primary_key=True, autoincrement=True)
prenom = db.Column(db.Text, nullable=False)
password = db.Column(db.String(100), nullable=False)
mail = db.Column(db.String(80), nullable=False)
@staticmethod
def identification(mail, password):
"""
Permet l'identification d'un utilisateur à partir d'un mail et d'un mot de passe fournis
Les deux arguments sont obligatoires
Parameters
----------
mail : str, required
Le mail fourni par le client
password : str, required
Le mot de passe fourni par le client
Returns
-------
app.models.users.Users
Une instance de la classe Users si l'identification est un succès, sinon retourne None
"""
utilisateur = Users.query.filter(Users.mail == mail).first()
if utilisateur and check_password_hash(utilisateur.password, password):
return utilisateur
return None
/pays
de routes/generales.py
@app.route("/pays")
@app.route("/pays/<int:page>")
def pays(page=1):
"""
Route permettant l'affichage des pays, avec une pagination possible
Parameters
----------
page : int, optional
Le numéro de la page à afficher (si non fourni, 1 par défaut)
Returns
-------
template
Retourne le template pays.html
"""
return render_template("pages/pays.html",
sous_titre="Pays",
donnees= Country.query.order_by(Country.name).paginate(page=page, per_page=app.config["PAYS_PER_PAGE"]))
Les fichiers, les variables, les classes et les fonctions doivent être nommés de manière logique et compréhensible. Ils doivent porter le nom de ce qu'ils sont ou font vraiment.
Les packages (par exemple routes
ou templates
) doivent être rangés en différents modules:
Aucun chemin absolu ne doit se trouver dans l'application:
Le seul chemin absolu qu'il y aura est éventuellement un chemin absolu vers la base SQLite: il sera à indiquer dans le fichier .env
.
Toute valeur de configuration (comme le PER_PAGE de la pagination, des URL d'API, etc.) doit être sortie de l'application pour être mise en variable d'environnement (donc dans .env
).
Comme vu en Séance2, les liens internes se font via url_for()
dans les routes et les templates. L'écriture de ces liens en dur est à proscrire, le domaine et le port changent constamment.
La gestion des erreurs a été vue en Séance5; elle implique notamment:
try
et except
Aucune erreur 4XX ou 5XX ne devra être retournée directement à l'utilisateur: une page indiquant qu'une erreur est survenue devra être retournée. C'était l'objet de l'exercice REF-1 de la Séance5.
Plusieurs solutions pour me fournir une base de données :
.sqlite
(il ne doit pas se trouver dans le dépôt du code mais m'être envoyé à part): ce fichier peut contenir uniquement des tables vides, ou bien rempli avec des donnéesCREATE
GRANT
notamment)INSERT
)Dans tous les cas, si une base de données est adossée à l'application, il faudra me fournir le MRD (modèle relationnel de données) de la base de données correctement représenté.
Le fichier requirements.txt
, mis à la racine de l'application, est obligatoire. Il permet d'indiquer toutes les dépendances de l'application et leurs versions. Il est nécessaire pour pouvoir lancer l'application sur d'autres machines (dont la mienne pour la correction).
Pour le générer, se rendre à la racine de l'application (à côté du fichier run.py
). Activer l'environnement virtuel.
Simplement exécuter la commande suivante: pip freeze > requirements.txt
.
Le README est le fichier qui donne une première documentation de l'application. Il est présent à la racine de l'application. C'est ce fichier qui est rendu par Github quand on va sur un dépôt.
Pour le devoir, voici ce que le README doit indiquer:
.env
, avec une description de la valeur à leur attribuer ou une valeur par défaut à mettreLes instructions d'installation et de lancement de l'application doivent être le plus précises possibles, et sont pour la plupart évidentes. Il faut se mettre à la place d'une personne qui n'y connaît rien et qui doit installer puis lancer une application en Python. Des exemples d'étapes:
.env
?run.py
Le devoir sera obligatoirement rendu via un dépôt disponible sur Github, les cours de Git étant désormais passés. Aucune autre forme de rendu (.zip, etc.) ne sera accepté.
Note 1 : Il est fortement recommandé de développer l'application en utilisant Git et Github. C'est le moyen le plus viable et rapide de développer en groupe.
Note 2 : Déployer sur le cloud est optionnel et ne rentre pas en compte dans la note. Vous pouvez le faire par pur plaisir, ou pour vérifier que votre dépôt de code est correct et fonctionne bien.
Ne doivent pas être présents dans le dépôt les éléments suivants:
env/
.env
Vous trouverez un exemple de .gitignore
ici
Voici toutes les étapes que je jouerai dans l'ordre pour lancer votre application. Je les indique ici pour que vous les testiez de votre côté avant de me rendre le devoir. Si ça ne fonctionne pas de votre côté, ça ne risque pas de fonctionner chez moi; ce n'est donc pas la peine de rendre le devoir.
On suppose que j'ai Python 3.6 installé sur ma machine Ubuntu 20.04 (ou plus).
git clone lien_vers_le_depot.git
cd depot/
virtualenv env -p python3
.sqlite
à côté de run.py
, ou installation d'un serveur.env
à côté de run.py
à partir des variables indiquées dans le READMEsource env/bin/activate
pip install -r requirements.txt
python run.py