Ci-dessous, les différences entre deux révisions de la page.
| Prochaine révision | Révision précédente | ||
| dev:python:flask:flask-sqlalchemy:activer-contraintes-fk-sqlite-avec-flask-sqlachemy [2025/08/29 16:56] – créée yoann | dev:python:flask:flask-sqlalchemy:activer-contraintes-fk-sqlite-avec-flask-sqlachemy [2025/08/31 09:10] (Version actuelle) – yoann | ||
|---|---|---|---|
| Ligne 1: | Ligne 1: | ||
| {{tag> | {{tag> | ||
| - | : | ||
| ====== Flask-SQLAlchemy : Forcer la vérification des contraintes sur une base SQLite3 ====== | ====== Flask-SQLAlchemy : Forcer la vérification des contraintes sur une base SQLite3 ====== | ||
| Ligne 46: | Ligne 45: | ||
| - | Lorsqu' | + | Lorsqu' |
| <code python> | <code python> | ||
| - | # Ce comportement est correct | + | >>> |
| + | >>> | ||
| - | # Ce comportement est anormal | + | >>> |
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | <class ' | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | ... | ||
| + | ... | ||
| + | r1-A | ||
| + | r1-B | ||
| + | >>> | ||
| + | >>> | ||
| + | 1 | ||
| + | >>> | ||
| + | 1 | ||
| + | >>> | ||
| + | 1 | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| </ | </ | ||
| - | via le client en ligne de commande, on peut afficher le contenu de notre fichier base de données : | + | via le client |
| - | <code python> | + | <code bash> |
| + | sqlite3 instance/ | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | sqlite> -- Affiche la structure de la table | ||
| + | sqlite> .schema categories | ||
| + | CREATE TABLE categories ( | ||
| + | id INTEGER NOT NULL, | ||
| + | label VARCHAR(50) NOT NULL, | ||
| + | description TEXT, | ||
| + | parent_id INTEGER, | ||
| + | PRIMARY KEY (id), | ||
| + | FOREIGN KEY(parent_id) REFERENCES categories (id) | ||
| + | ); | ||
| + | sqlite> | ||
| + | sqlite> -- affiche les valeurs nulles et les entêtes | ||
| + | sqlite> .nullvalue NULL | ||
| + | sqlite> .headers on | ||
| + | sqlite> | ||
| + | sqlite> -- Affiche le contenu de la table categories | ||
| + | sqlite> SELECT * FROM categories; | ||
| + | id|label|description|parent_id | ||
| + | 1|root|NULL|NULL | ||
| + | 2|r1-A|NULL|1 | ||
| + | 3|r1-B|NULL|1 | ||
| + | 4|une catégorie invalide|NULL|666 | ||
| + | </ | ||
| + | |||
| + | Ici on voit bien que la catégorie d' | ||
| + | |||
| + | La requête d' | ||
| + | <code sql> | ||
| + | -- la requête suivante passée depuis sqlite3 ne retourne pas d' | ||
| + | INSERT INTO categories (label, | ||
| + | </ | ||
| + | |||
| + | On affiche la table categories, on peut voir que le nouvel enregistrement a été créée : | ||
| + | < | ||
| + | sqlite> SELECT * FROM categories; | ||
| + | id|label|description|parent_id | ||
| + | 1|root|NULL|NULL | ||
| + | 2|r1-A|NULL|1 | ||
| + | 3|r1-B|NULL|1 | ||
| + | 4|une catégorie invalide|NULL|666 | ||
| + | 5|un autre test|NULL|777 | ||
| + | </ | ||
| + | |||
| + | En affichant la configuration du fichier de base de données on peut voir une option **enable_fkey** positionnée à '' | ||
| + | |||
| + | <code txt [highlight_lines_extra=" | ||
| + | sqlite> .dbconfig | ||
| + | defensive on | ||
| + | dqs_ddl on | ||
| + | dqs_dml on | ||
| + | enable_fkey off | ||
| + | enable_qpsg off | ||
| + | | ||
| + | enable_view on | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | | ||
| + | reverse_scanorder off | ||
| + | stmt_scanstatus off | ||
| + | trigger_eqp off | ||
| + | | ||
| + | writable_schema off | ||
| + | </ | ||
| + | |||
| + | < | ||
| + | Si on passe cette variable de configuration a '' | ||
| + | </ | ||
| + | |||
| + | <file txt [highlight_lines_extra=" | ||
| + | sqlite> .dbconfig enable_fkey on | ||
| + | enable_fkey on | ||
| + | sqlite> INSERT INTO categories (label, | ||
| + | Runtime error: FOREIGN KEY constraint failed (19) | ||
| + | </ | ||
| + | |||
| + | C'est bien une variable de configuration pour notre base de données SQLite3 qui permet d' | ||
| + | |||
| + | Le code ci-dessous proposé sur la [[https:// | ||
| + | |||
| + | |||
| + | <code python | ||
| from flask import Flask | from flask import Flask | ||
| from flask_sqlalchemy import SQLAlchemy | from flask_sqlalchemy import SQLAlchemy | ||
| Ligne 80: | Ligne 205: | ||
| </ | </ | ||
| + | |||
| + | Après modification du code d' | ||
| + | |||
| + | <code python [highlight_lines_extra=" | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | >>> | ||
| + | Traceback (most recent call last): | ||
| + | File "/ | ||
| + | self.dialect.do_execute( | ||
| + | File "/ | ||
| + | cursor.execute(statement, | ||
| + | sqlite3.IntegrityError: | ||
| + | </ | ||
| ===== Références ===== | ===== Références ===== | ||
| * [[https:// | * [[https:// | ||
| + | * [[https:// | ||