Modèles plans et vues pour les pays¶
Modèles, plans et vues
Créez le package nommé models
(un dossier) dans le dossier mobility
.
Ajoutez dans ce nouveau package un fichier nommé country.py
et ajoutez-y le code suivant :
mobility/models/country.py
from mobility.db import get_db
def get_country_list():
db = get_db()
return db.execute('SELECT * FROM country ORDER BY iso_country').fetchall()
def search_by_iso(iso_country: int):
db = get_db()
return db.execute('SELECT * FROM country WHERE iso_country=?', (iso_country,)).fetchall()
Avertissement
Il est TRÈS important d'utiliser le mécanisme de remplacement avec des ?
.
En effet, si vous faites
db.execute("SELECT * FROM country WHERE iso_country=" + iso_country)
au lieu de
db.execute("SELECT * FROM country WHERE iso_country=?", (iso_country,) )
ce qui est syntaxiquement correct, l'utilisateur peut envoyer un iso_country
tel que iso_country OR 1=1
, ce qui
introduit une tautologie et permet d'extraire... l'entièreté de la base de données !
En fonction de l'utilisation du résultat, cela peut être extrêmement grave. La RGPD prévoit des amendes jusqu'à 20 millions d'euros pour ce genre de manque de prévoyance élémentaire.
La fonction get_country_list
retourne une liste de tous les pays dans la base de données, ordonnée par code iso.
La fonction search_by_iso
retourne le code iso, ainsi que le nom du pays dont le code iso est passé en paramètre.
Ajoutez cette classe en dessous des fonctions créées précédemment.
mobility/models/country.py
class Country:
def __init__(self, name, iso_country):
self.name = name
self.iso_country = iso_country
def delete(self):
db = get_db()
db.execute("DELETE FROM country WHERE iso_country=?", (self.iso_country,))
db.commit()
def save(self):
db = get_db()
db.execute("INSERT INTO country(iso_country,name) VALUES(?, ?)",
(self.iso_country, self.name))
db.commit()
@staticmethod
def get(iso_country: int):
db = get_db()
data = db.execute(
'SELECT * FROM country WHERE iso_country=?', (iso_country,)).fetchone()
if data is None:
return None
else:
return Country(data["name"], data["iso_country"])
La classe Country
est une classe qui représente un pays. Elle a deux attributs : name
et iso_country
.
Elle a aussi trois méthodes : delete
, save
et get
. La méthode delete
supprime le pays de la base de données, la méthode save
ajoute le pays à la base de données et la méthode get
retourne une instance de Country
à partir d'un code iso.
Nous allons créer une nouvelle page mobility/templates/country.html
qui va afficher la liste de tous les pays, en appelant la fonction get_country_list
. N'oubliez pas d'utiliser le principe d'héritage et d'étendre base.html
. Le fichier country.html
vous est déjà donné ci-dessous.
mobility/country.py
from flask import (
Blueprint, render_template
)
from mobility.models.country import get_country_list
bp = Blueprint('country', __name__)
# route code
@bp.route('/country')
def country_list():
countries = get_country_list()
return render_template("country.html", countries=countries)
mobility/templates/country.html
Solution (Essayez d'abord par vous-même)
{% extends "base.html" %}
{% block content %}
<h2>Country list</h2>
<table>
<tr>
<th>Name</th>
<th>ISO Code</th>
</tr>
{% for country in countries %}
<tr>
<td>{{ country['name'] }}</td>
<td>{{ country['iso_country'] }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
Interagir avec la base de données depuis le site web¶
Pour le moment, notre base de données est presque vide, les fonctions que nous avons écrites ne sont donc pas encore très utiles. Nous aimerions avoir la possibilité d'ajouter ou supprimer un pays dans la base de données depuis notre site web. Pour cela, nous allons ajouter deux nouvelles routes à notre plan.
mobility/country.py
@bp.route("/create_country", methods=["POST"])
def country_create():
iso_country = request.form["iso_country"]
if not search_by_iso(str(iso_country)):
print("Creating country")
name = request.form["name"]
country = Country(name, iso_country)
country.save()
print("Country already exists")
return redirect(url_for("country.country_list"))
@bp.route("/delete_country/<iso_country>")
def country_delete(iso_country):
country = Country.get(iso_country)
if country:
country.delete()
return redirect(url_for("country.country_list"))
Vous constatez dans votre IDE que les imports request
, redirect
, url_for
sont manquants. Ajoutez-les en haut de votre fichier.
Vous devez également importer la classe Country
et les fonctions search_by_iso_code
et get_country_list
depuis mobility/models/country.py
. Votre début de fichier devrait ressembler à ceci :
mobility/country.py
from flask import (
Blueprint, render_template, request, redirect, url_for
)
from mobility.models.country import get_country_list, search_by_iso, Country
bp = Blueprint('country', __name__)
Il reste à mettre à jour le template pour ajouter un formulaire pour ajouter une ville et un bouton pour supprimer une ville. Retournez dans votre fichier country.html et ajoutez le code suivant.
mobility/template/country.html
{% extends "base.html" %}
{% block content %}
<h2>Country list</h2>
<table>
<tr>
<th>Name</th>
<th>ISO Code</th>
</tr>
{% for country in countries %}
<tr>
<td>{{ country['name'] }}</td>
<td>{{ country['iso_country'] }}</td>
<td><a href="{{ url_for("country.country_delete", iso_country=country['iso_country']) }}">Delete</a></td>
</tr>
{% endfor %}
<h2>New country</h2>
<form method="post" action="{{ url_for("country.country_create") }}">
<div>
<label for="iso_country"> ISO Code: </label>
<input name="iso_country" id="iso_country" type="text" />
</div>
<div>
<label for="name">Name: </label>
<input name="name" id="name" type="text" />
</div>
<div>
<button type="submit">Add a country </button>
</div>
</table>
{% endblock %}
Nous avons créé un formulaire pour ajouter un pays ainsi qu'un bouton pour en supprimer un. Le formulaire envoie une requête POST à la route country_create
et le bouton envoie une requête GET à la route country_delete
.
N'oubliez pas d'ajouter la nouvelle route :
mobility/__init__.py
...
from . import country
app.register_blueprint(country.bp)
...
Testez votre application en lançant le serveur avec la commande flask --app=mobility --debug run
Dans votre navigateur, allez sur la page http://127.0.0.1:5000/country
.
Ensuite, ajoutez des pays à votre base de données en utilisant le formulaire que vous venez de créer. Vous pouvez aussi supprimer des pays en cliquant sur le bouton "Delete" à côté de chaque pays.
Vous devriez avoir une page qui ressemble à ceci :
Continuez en lisant le document pour ajouter les aéroports Modèles plans,et vues pour les aéroports.