Modèles plans et vues pour les aéroports

Pour vous habituer à l'utilisation de la base de données et la notion de clefs étrangères, ajoutez une table airport à votre base de données. Pour cela, modifiez le fichier schema.sql en ajoutant le code suivant sans supprimer le code que vous avez déjà mis.

mobility/schema.sql

DROP TABLE IF EXISTS airport;
CREATE TABLE airport(iata_code TEXT PRIMARY KEY,
                     name TEXT,
                     iso_country TEXT,
                     FOREIGN KEY (iso_country) REFERENCES country(iso_country)
                    );
INSERT INTO airport(iata_code,name, iso_country ) VALUES("ENF","Enontekio Airport", "FI");

Ce code ajoute une table airport à notre base de données et insère un aéroport. La table a trois colonnes : iata_code, name et iso_country. La colonne iata_code est une clef primaire, la colonne name est le nom de l'aéroport et la colonne iso_country est une clef étrangère qui fait référence à la colonne iso_country de la table country. Dans la base de données qui vous sera fournie, la table airport comprendra deux colonnes supplémentaires donnant respectivement la longitude et la latitude de l'aéroport. Dans le cadre de cet exercice, nous allons prendre une version simplifiée de cette table.

La procédure qui va suivre est très similaire à celle que nous avons suivie pour la table country. Créez un fichier que vous nommez airport.py dans le dossier models et ajoutez-y le code suivant. Ensuite, complétez le code ci-dessous :

mobility/models/airport.py

def get_airport_list():
  # TODO
  # Retourne la liste des aéroports, ainsi que le nom du pays correspondant
  # trier par ordre alphabétique sur base du nom du pays

def search_airport_by_iata_code(iata_code: str):
  # TODO
  # Retourne la ligne correspondant à l'aéroport portant le code iata "iata_code"
class Airport:

   def __init__(self, iata_code, name, iso_country):
      # TODO
      # Constructeur de la classe

   def delete(self):
      # TODO
      # Retire l'aéroport de la DB

   def save(self):
      # TODO
      # Sauvegarde l'aéroport dans la DB

   @staticmethod
   def get(iata_code: str):
      # Retourne un objet Aéroport construit à partir des informations de la DB
      # récupérer à partir du code iata "iata_code"
      # Retourne none si aucun aéroport avec le code iata "iata_code"
      # se trouve dans la DB
      # Vous pouvez vous insprirer de la classe Country implémentée précédemment

mobility/models/airport.py

Solution (Essayez d'abord par vous-même)
from mobility.db import get_db

def get_airport_list():
   db = get_db()
   return db.execute(
      'SELECT * FROM airport')


def search_airport_by_iata_code(iata_code: str):
   db = get_db()
   return db.execute('SELECT * FROM airport WHERE iata_code=?', (iata_code,)).fetchall()

class Airport:

   def __init__(self, iata_code, name, iso_country):
      self.iata_code = iata_code
      self.name = name
      self.iso_country = iso_country

   def delete(self):
      db = get_db()
      db.execute("DELETE FROM airport WHERE iata_code=?", (self.iata_code,))
      db.commit()

   def save(self):
      db = get_db()
      db.execute("INSERT INTO aiport(iata_code,name, iso_country ) VALUES(?, ?, ?)", ( self.iata_code, self.name, self.iso_country))
      db.commit()


   @staticmethod
   def get(iata_code: str):
      db = get_db()
      data = db.execute('SELECT * FROM airport WHERE iata_code=?', (iata_code,)).fetchone()

      if data is None:
         return None
      else:
         return Airport(data["iata_code"], data["name"], data["iso_country"])

Créez ensuite le fichier airport.py dans le dossier mobility.

mobility/airport.py

from flask import (
   Blueprint, redirect, render_template, request, url_for
)

from mobility.models.airport import Airport
from mobility.models.airport import get_airport_list,search_airport_by_iata_code

bp = Blueprint('airport', __name__)

# Define the routes code
@bp.route('/')
def airport_list():
   # TODO
   # Page principal qui affiche la liste des aéroports
   # avec leur nom, code IATA et le nom de leur pays correspondant

@bp.route("/create_airport", methods=["POST"])
def airport_create():
   # TODO
   # Page permettant d'ajouter un aéroport, similaire à "create_country"

@bp.route("/delete_airport/<iata_code>")
def airport_delete(iata_code):
   # TODO
   # Page permettant de retirer un aéroport, similaire à "delete_country"

mobility/airport.py

Solution (Essayez d'abord par vous-même)
from flask import (
   Blueprint, redirect, render_template, request, url_for
)

from mobility.models.airport import Airport
from mobility.models.airport import get_airport_list,search_airport_by_iata_code

bp = Blueprint('airport', __name__)

# Define the routes code
@bp.route('/')
def airport_list():
   airports = get_airport_list()
   return render_template("airport.html", airports=airports)

@bp.route("/create_airport", methods=["POST"])
def airport_create():
   iata_code = request.form["iata_code"]
   if not search_airport_by_iata_code(str(iata_code)):
      name = request.form["name"]
      iso_country = request.form["iso_country"]
      airport = Airport(iata_code, name, iso_country)
      airport.save()
   return redirect(url_for("airport.airport_list"))

@bp.route("/delete_airport/<iata_code>")
def airport_delete(iata_code):
   airport = Airport.get(iata_code)
   if airport:
      airport.delete()
   return redirect(url_for("airport.airport_list"))

Complétez le fichier airport.html pour avoir la fonctionnalité d'ajouter et de supprimer des aéroports à l'aide d'une interface semblable à ce que nous avons fait pour les pays.

mobility/templates/airport.html

Solution (Essayez d'abord par vous-même)
{% extends "base.html" %}
{% block content %}

<h2>Airports list</h2>
<table>
    <tr>
        <th>IATA code</th>
        <th>Name</th>
        <th>Country</th>
    </tr>
    {% for airport in airports %}
    <tr>
        <td>{{ airport['iata_code'] }}</td>
        <td>{{ airport['name'] }}</td>
        <td>{{ airport['cname'] }}</td>
        <td><a href="{{ url_for("airport.airport_delete", iata_code=airport['iata_code']) }}">Delete</a></td>
    </tr>
    {% endfor %}
 </table>
 <h2>New airport</h2>
 <form method="post" action="{{ url_for("airport.airport_create") }}">
    <div>
       <label for="iata_code"> IATA Code: </label>
       <input name="iata_code" id="iata_code" type="text" />
    </div>
    <div>
       <label for="name">Name: </label>
       <input name="name" id="name" type="text" />
    </div>
    <div>
       <label for="iso_country">ISO Code: </label>
       <input name="iso_country" id="iso_country" type="text" />
    </div>
 <div>
    <button type="submit">Add an airport </button>
 </div>
{% endblock %}

Enfin n'oubliez pas de mettre à jour le fichier __init__.py dans le dossier mobility en ajoutant et modifiant les lignes suivantes.

mobility/__init__.py

from . import country, airport
app.register_blueprint(country.bp)

app.register_blueprint(airport.bp)
app.add_url_rule('/', endpoint='index')

Ajoutez un pays et puis un aéroport à votre base de données par le formulaire en utilisant le même code ISO. Si vous ajoutez un aéroport avec un code ISO sans pays correspondant, l'aéroport ne sera pas affiché.

Voici un exemple de ce que vous devriez voir sur la page airport.html.

../../_images/airport_final.png

Continuez en lisant Utiliser la DB disponible sur moodle!.