Oubliez SQL avec SQLAlchemy Pycon.fr 2009 Michael Scherer
Origine Ordinateur : Appareil électronique capable [...] d’effectuer des traitements automatisés de données
Stockage ? ● XML ● Structure binaire ● Json ● Fichiers et répertoire ● Objets
SQL ● Très utilisé dans le monde ● Gestion de données par table ● Schéma de description des données
SQL et Python PEP 0249
Problème de SQL
Standard ? Un champ avec un auto incrément
Mysql CREATE TABLE animals ( id INT NOT NULL AUTO_INCREMENT, name TEXT, PRIMARY KEY (id) );
SQLite CREATE TABLE animals( id INTEGER PRIMARY KEY, name TEXT );
Postgresql CREATE TABLE animals( id SERIAL, name TEXT );
Oracle, Firebird, MS-SQL, etc
SQL Différences dans les types
SQL Différences dans les fonctions
ORM Object Relational Mapper
Avantages Ne pas avoir à connaitre SQL
Avantages Couche d'abstraction
Avantages Portabilité entre les divers SGBD
Avantages Portabilité entre les différentes versions d'un SGDB
Avantages Gestion de plus haut niveau
Avantages Protection contre les attaques de type SQL injection
Exemples d'ORM Active Record ( Ruby ) Class::DBIx ( Perl ) Hibernate ( Java )
Exemples d'ORM python Storm L'orm de Django SQL Object SQL Alchemy
En vrac ● Version ● Date de 2006 ● Licence MIT ● lignes de code python
Utilisé par ● Trac ● Pagoda ●.... ● Reddit.com ● Virgin Charter
Support des SGBDs ● SQLite ● MySQL ● PostgreSQL ● Oracle ● Firebird ● MS-SQL ●...
Problèmes des ORMs
Cache la base de données
Faux ● Accès direct possible via la requête de son choix ● Possibilité de voir le SQL généré à l'utilisation
Force l'usage d'un dénominateur commun
Faux ● Utilisation de types spécifiques possible ● PgInet ● MSBigInteger ● Ajout de types personnalisés
Mauvais pour les performances
Faux ● Chargement paresseux ( lazy loading ) ● Chargement avide ( eager load ) ● Possibilité d'utiliser sa propre requête SQL optimisé ● Génération de SQL via un moteur d'optimisation ● Utilisation d'un pool de requêtes
If all you have is a hammer everything starts to look like a nail
Guide rapide
Déclarer la base from sqlalchemy import create_engine engine = create_engine( 'sqlite:///:memory:' )
Déclarer les tables metadata = MetaData() animals = Table('animals', metadata, Column('id', Integer, primary_key = True), Column('name', String(30), nullable = False), )
Création des tables metadata.create_all(engine)
Creation des classes class Animal(object): def __init__(self, name): self.name = name def __repr__(self): return " " % self.name
Lien entre table et objet from sqlalchemy.orm import mapper mapper(animals, Animal)
Connexion à la base from sqlalchemy.orm import sessionmaker session = sessionmaker(bind=engine)
Ajout d'un objet castor = animal('Victor') session.add(castor) # envoi vers la base session.commit()
Requêtes
Utilisation de Query >>> for a in session.query(Animal):... print a.name Victor
Filtrage >>> session.query(Animal).filter( Animal.name.like('V%')).first() Victor
Filtrage Utilisation proche de Python ● Slices -> LIMIT OFFSET ● Possibilités de chainer les filtres comme des appels de fonctions
Trucs avancés
Utilisation de pickle Stockage d'objet python directement dans la base
Héritage Formalise l'héritage dans la base
Système de cache Possibilité de s'insérer dans le moteur de requêtes
Sharding Répartition des données sur plusieurs bases
Migrate Gestion des changements de schémas
Elixir Couche déclarative au dessus de SQLAlchemy
elixir.ext.versionned Gestion automatique de version des objets
elixir.ext.list Simule une structure de liste
elixir.ext.encrypted Chiffrage à la volée des entrées
?