User Tools

Site Tools


proj_cmi_l2:bd

Licence Sciences, Technologies, Santé / Parcours MISMI

L2 CMI ISI - 4TIN401U Projet de programmation

Simplicity is prerequisite for reliability

Edsger Dijkstra


Base de données

Nous allons tirer profit de la connaissance que vous avez déjà en bases de données. Nous allons construire une base de données pour stocker les informations sur les grands quotidiens dont nous extrayons les unes.

  • Nous allons supposer que vous avez sur votre poste un gestionnaire de bases de données MySQL (easyPHP sur Win, XAMPP sur OS X).
    • Une fois ce gestionnaire lancé (il fait tourner un serveur Apache, et un moteur de bases de données MySQL), vous pouvez accéder à une vue sur les bases de données qui sont gérées sur votre machine.

Quelles relations ?

Nous avons convenu de stocker les informations concernant

  • Les quotidiens (nom, URL et id), où
    • id est un identifiant interne comme clé primaire – quoique ici le nom du quotidien est une clé, il est unique, c'est une marque déposée).
id nom URL
4 Libération www.liberation.fr
19 20 minutes www.20minutes.fr
  • Les unes (titre, URL, date, id), où
    • id est un identifiant interne comme clé primaire
    • titre est le titre de la une (chaîne de caractères)
    • URL est l'URL relative; en d'autres mots, l'URL menant à l'article est obtenue en y préfixant l'URL du quotidien stockée dans la relation quotidien
    • date est un objet date stockant la date sous le format jj/mm/aaaa

Il nous faut aussi stockée l'information qui associe une une au quotidien où elle est parue. C'est une relation très simple qui stocke l'association entre unes et quotidiens.

  • (id du quotidien, id de la une)

Sa simplicité nous conduit, plutôt que de construire une relation à part entière, à stocker la clé du quotidien avec la une elle-même. L'information sur une une devient donc:

  • Les titres (titre, URL, date, id, id_quotidien), où
    • id_quotidien est une clé étrangère, c'est-à-dire empruntée à une autre relation dans la base.
id titre URL date id_quotidien
101 Perturbateurs endocriniens : urgence sanitaire dans nos placards planete/2017/02/27/perturbateurs-endocriniens-urgence-sanitaire-dans-nos-placards_1551518 28/02/2017 4
89 Pourquoi un poisson tropical a-t-il été pêché en mer du Nord? lille/2021915-20170228-pourquoi-poisson-tropical-peche-mer-nord 28/02/2017 19

Construire la base de données

Les relations d'un modèle de données (souvent décrit à l'aide d'un schéma entités-association), sont implémentées à l'aide de tables. C'est pratique, c'est la vision qu'on a d'un produit cartésien: une relation n'est rien d'autre qu'un sous ensemble de l'ensemble qui portent les modalités de chacun des attributs.

Les instructions SQL quivantes permettent de créer les tables quotidiens et unes.

  • Remarquez qu'il est nécessaire de spécifier la taille des objets (entiers, chaînes de caractères).
  • Les instructions apparaissant à la fin permettent de spécifier les valeurs qui jouent le rôle de clé primaire ou de clé étrangère.
  • On peut aussi passer par l'interface de gestion phpmyadmin pour construire les tables. Mais il faut nécessairement utiliser l'instruction SQL ALTER pour introduire la clé étrangère (vue comme une contrainte sur les attributs de la table unes).

Au passage, vous verrez les requêtes SQL qui correspondent à toutes les manipulations effectuées sur la base à l'aide de l'interface. C'est une bonne façon d'apprendre à formuler des requêtes.

alaune.sql
--
-- Base de données :  `alaune`
--
 
-- --------------------------------------------------------
 
--
-- Structure de la table `quotidiens`
--
 
CREATE TABLE `quotidiens` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `nom` VARCHAR(30) NOT NULL,
  `URL` VARCHAR(30) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
-- --------------------------------------------------------
 
--
-- Structure de la table `unes`
--
 
CREATE TABLE `unes` (
  `id` INT(11) NOT NULL AUTO_INCREMENT,
  `titre` VARCHAR(100) NOT NULL,
  `URL` VARCHAR(100) NOT NULL,
  `date` DATE NOT NULL,
  `quotidien_id` INT(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
 
--
-- Index pour les tables exportées
--
 
--
-- Index pour la table `quotidiens`
--
ALTER TABLE `quotidiens`
  ADD PRIMARY KEY (`id`);
 
--
-- Index pour la table `unes`
--
ALTER TABLE `unes`
  ADD PRIMARY KEY (`id`),
  ADD KEY `quotidien_id` (`quotidien_id`);
 
--
-- Contraintes pour les tables exportées
--
 
--
-- Contraintes pour la table `unes`
--
ALTER TABLE `unes`
  ADD CONSTRAINT `id_quotidien` FOREIGN KEY (`id`) REFERENCES `quotidiens` (`id`);

Manipuler la base de données (connexion)

Il reste à voir ce qu'il faut ajouter au code de notre application pour stocker dans la base de données les unes qui sont extraites.

Rappelons le code qui permet de se connecter à la base:

import mysql.connector
import json
 
config = json.loads(open('config', 'r').read())
 
cnx = mysql.connector.connect(** config)
 
cursor = cnx.cursor()

On suppose ici que les identifiants de connexion sont inscrits dans un fichier stocké sur le serveur (ils ne sont pas dans le code python lui-même). Il faudra éviter de poser ce fichier config sur le serveur github. On y posera plutôt un fichier exemple.

Le fichier suit la structure:

{
  "user": "user_name",
  "password": "password",
  "host": "localhost",
  "database": "database_name"
}

et les valeurs à inscrire dépend de votre gestionnaire de base de données. Le paramètre host est pour l'instant localhost puisque l'on fait tourner notre code en local.


Manipuler la base de données (requêtes)

La librairie python mysql.connector permet d'interroger la base de données. Il faut pour cela construire des requêtes dans le code python lui-même et en demander l'exécution. Le résultat est alors retournée, le plus souvent sous la forme d'un objet comme un tableau dont on peut parcourir les entrées (les résultats de la requête).

add_quotidien = ("INSERT INTO quotidiens(nom, URL) VALUES (%s, %s)")
 
data_quotidien = ('20 minutes', 'www.20minutes.fr')
 
cursor.execute(add_quotidien, data_quotidien)

On fabrique d'abord une chaîne de caractères qui correspond à la requête à effectuer.

  • Il faut donc se pencher sur la syntaxe SQL – consultez la documentation, fouillez le web !
  • On y insère des “stubs” qui correspondent à des valeurs particulières qui seront insérées le moment venu.
    • L'intérêt de procéder ainsi est que la même requête peut être ré-utilisé plusieurs fois en variant ses paramètres.

Une version alternative utilise un dictionnaire:

add_quotidien = ("INSERT INTO quotidiens (nom, URL) VALUES (%(nom)s, %(URL)s)")
 
data_quotidien = {
  'nom': 'Le Monde',
  'URL': 'www.lemonde.fr'
}
 
cursor.execute(add_quotidien, data_quotidien)

On peut à l'inverse interroger la base pour obtenir des informations qui y sont stockées. ON utilise là encore des requêtes préparées.

get_quotidien = ("SELECT id, URL FROM quotidiens WHERE nom LIKE (%s)")
 
nom_quotidien = ('Libération',)
 
cursor.execute(get_quotidien, nom_quotidien)
 
for (id, URL) in cursor:
  print("Quotidien id {}, URL {}".format(id, URL))

ou à l'aide d'un dictionnaire:

get_quotidien = ("SELECT id, URL FROM quotidiens WHERE nom LIKE (%(nom)s)")
 
nom_quotidien = {'nom': '20 minutes'}
 
cursor.execute(get_quotidien, nom_quotidien)
 
for (id, URL) in cursor:
  print("Quotidien id {}, URL {}".format(id, URL))

Exercice

Rassemblez dans un fichier python modele_donnees.py (qui deviendra un “package” de votre application, vous ferez depuis votre serveur flask un from modele_donnees import *) des fonctions qui:

  • Etablir une connexion à la base de données et retourne un curseur qui peut exécuter des requêtes.
  • Insère dans la base de données un nouveau quotidien.
    • Votre fonction
      def insert_quotidien(** quotidien)

      prendra la précaution de vérifier si le quotidien existe déjà dans la base ou non.

    • La fonction reçoit en paramètre un dictionnaire python contenant tous les attributs d'un quotidien (d'où l'utilisation du double astérisque *).
  • Insère dans la base une nouvelle une.
    • Votre fonction
      def insert_une(** une)

      prendra la précaution de vérifier si la une de ce quotidien existe déjà dans la base ou non.

    • La fonction reçoit en paramètre un dictionnaire python contenant tous les attributs de la une, y compris le nom du quotidien.
  • Interroge la base pour en obtenir les unes d'un quotidien.
    • Votre fonction
      def select_une(quotidien)

      devra d'abord obtenir la clé primaire du quotidien, utilisée comme clé étrangère dans la table des unes.

    • La fonction reçoit en paramètre une chaîne de caractère contenant le nom du quotidien.

Une fois les définitions de vos fonctions complétées, le code suivant doit pouvoir tourner sans problème.

modele_donnees.py
def insert_quotidien(** quotidien)
    # to do
    # la variable quotidien contient un dictionnaire décrivant le quotidien
 
def insert_une(** une):
    # to do
    # la variable une contient un dictionnaire décrivant la une
    # la fonction devra auparavant interroger la base pour connaitre
    # le id du quotidien apparaissant en cle etrangere dans la table unes
 
def select_une(quotidien):
    # to do
    # la fonction devra auparavant interroger la base pour connaitre
    # le id du quotidien apparaissant en cle etrangere dans la table unes
 
if __name__ == '__main__':
    quotidien = {'nom': 'La Presse', 'www.lapressse.ca'}
    insert_quotidien(quotidien)
 
    une = {}
    une['titre'] = "Devant le Congrès, Trump fait l'éloge d'une «nouvelle fierté nationale»"
    une['URL'] = 'international/etats-unis/201702/28/01-5073982-devant-le-congres-trump-fait-leloge-dune-nouvelle-fierte-nationale.php
    une['date'] = '01/03/2017'
    insert°une(une)
 
    select_une('La Presse')

Retour à la page d'accueil du cours

proj_cmi_l2/bd.txt · Last modified: 2017/03/01 10:43 by melancon