SQLAlchemy Déclaratif
Kesako ?
JJ   Fonctionnalité implémentée à partir de SQLAlchemy 0.5
JJ   Backporté en 0.4 pour nos besoins
JJ   Nouvelle manière de définir les tables et leurs relations
JJ   L’avenir de SQLAlchemy ?




                                                                 1
Avantages
JJ   SQLAlchemy
JJ   P
      ermet d’avoir une meilleure visibilité sur la définition de notre base
     de données
JJ   Facilite l’écriture de tests




                                                                                2
Définition d’une table
Imports nécessaires
import sqlalchemy
import zope.interface
from arsia.db.pgsql import base, DeclarativeBase



Interface implémentée par la table
class IBovin(zope.interface.Interface):
	 ‘‘‘ Marker interface for bovines ‘‘‘




                                                   3
Définition d’une table
Définition de la table
class Bovin(DeclarativeBase, base.MappedClassBase):
	 ‘‘‘ Mapper for the bovine table ‘‘‘
	zope.interface.implements(IBovin)

	   __tablename__ = u’bovin’

	   # Columns
	   mark_nr = sqlalchemy.Column(‘mark_nr’, sqlalchemy.Text, nullable=False,
                                primary_key=True, unique=True)
	   birth_date = sqlalchemy.Column(‘begin_date’, sqlalchemy.DateTime,
                                   nullable=False)
	   name = sqlalchemy.Column(‘denomination’, sqlalchemy.Text)




                                                                              4
Définition d’une table
Définition du schéma
class Bovin(DeclarativeBase, base.MappedClassBase):
	...

	   __tablename__ = u’bovin’
	   __table_args__ = {‘schema’: ‘cerise’}



Définition d’une relation
class Bovin(DeclarativeBase, base.MappedClassBase):
	...

	@classmethod
	 def __declare_last__(cls):
	 ‘‘‘ Defines the relations ‘‘‘
	 from mappers import mother
	 Bovin.mother = sqlalchemy.orm.relation(mother.Mother,
                                        lazy=False,
                                        uselist=False)
Les relations doivent être définie sur un objet pour lequel le mapper a été créé




                                                                                   5
Définition d’une table
Autre manière de définir une relation
class Bovin(DeclarativeBase, base.MappedClassBase):
	...

Bovin.mother = sqlalchemy.orm.relation(Mother,
                                       lazy=False,
                                       uselist=False)



Définition d’un index
class Bovin(DeclarativeBase, base.MappedClassBase):
	...

sqlalchemy.Index(
	‘mark_nr_idx’,
	Bovin.__table__.c.mark_nr)




                                                        6
Définition d’une table
Définition d’une contrainte
class Bovin(DeclarativeBase, base.MappedClassBase):
	...

	 __tablename__ = u’bovin’
	 __table_args__ = (
		 sqlalchemy.CheckConstraint(‘mark_nr != name’, name=’test_constraint’),
		     {‘schema’: ‘cerise’})

	   # Columns




                                                                            7
Activation de la réflexion des tables
Modification de la classe DeclarativeBase
try:
	 from sqlalchemy.ext.declarative import DeferredReflection
except ImportError:
	 from arsia.db.core.declarative import DeferredReflection

DeclarativeBase = sqlalchemy.ext.declarative.declarative_base(cls=DeferredReflection)




                                                                                        8
Méthodes et propriétés de bases
mapper_instance.session
Renvoi la session associée à l’objet courant ou une nouvelle session


mapper_instance.asDict(self)
Renvoi l’objet courant sous la forme d’un dictionnaire


mapper_instance.clone(self)
Renvoi une copie de l’objet courant


mapper_instance.update(self, flush=True, commit=False)
Met à jour l’objet courant dans la DB


mapper_instance.insert(self, flush=True, commit=False)
Insert l’objet courant dans la DB


mapper_instance.save_or_update(self, flush=True, commit=False)
Insert ou met à jour l’objet courant dans la DB




                                                                       9
Méthodes et propriétés de base
mapper_instance.save
mapper_instance.add
Aliases de mapper_instance.insert


Mapper.exists(cls, **kwargs)
Renvoi un booléen si une ligne dans la base de donnée correspond aux filtres données
Exemple : Bovin.exists(mark_nr=u’BE12345678’)


Mapper.get(cls, **kwargs)
Renvoi une liste de résultat qui correspond aux filtres données
Exemple d’utilisation : Bovin.get(snun_cde=u’BE12345678-0101’)


Mapper.first(cls, **kwargs)
Renvoi le premier résultat qui correspond aux filtres données
Exemple d’utilisation : Bovin.fist(mark_nr=u’BE12345678’)




                                                                                       10
Questions




            11
Liens
JJ   I
      mplémentation dans arsia.db.pgsql : http://svn.arsia.affinitic.be/
     Arsia/zope/arsia.db.pgsql/trunk/src/arsia/db/pgsql/mappers/
JJ   I
      mplémentation dans arsia.db.oracle : http://svn.arsia.affinitic.be/
     Arsia/zope/arsia.db.oracle/trunk/src/arsia/db/oracle/mappers/
JJ   Notre version de SQLAlchemy : http://hg.affinitic.be/sqlalchemy/
JJ   Documentation : http://docs.sqlalchemy.org/en/rel_0_7/orm/
      extensions/declarative.html




                                                                             12

Sqlalchemy declaratif

  • 1.
  • 2.
    Kesako ? JJ Fonctionnalité implémentée à partir de SQLAlchemy 0.5 JJ Backporté en 0.4 pour nos besoins JJ Nouvelle manière de définir les tables et leurs relations JJ L’avenir de SQLAlchemy ? 1
  • 3.
    Avantages JJ SQLAlchemy JJ P ermet d’avoir une meilleure visibilité sur la définition de notre base de données JJ Facilite l’écriture de tests 2
  • 4.
    Définition d’une table Importsnécessaires import sqlalchemy import zope.interface from arsia.db.pgsql import base, DeclarativeBase Interface implémentée par la table class IBovin(zope.interface.Interface): ‘‘‘ Marker interface for bovines ‘‘‘ 3
  • 5.
    Définition d’une table Définitionde la table class Bovin(DeclarativeBase, base.MappedClassBase): ‘‘‘ Mapper for the bovine table ‘‘‘ zope.interface.implements(IBovin) __tablename__ = u’bovin’ # Columns mark_nr = sqlalchemy.Column(‘mark_nr’, sqlalchemy.Text, nullable=False, primary_key=True, unique=True) birth_date = sqlalchemy.Column(‘begin_date’, sqlalchemy.DateTime, nullable=False) name = sqlalchemy.Column(‘denomination’, sqlalchemy.Text) 4
  • 6.
    Définition d’une table Définitiondu schéma class Bovin(DeclarativeBase, base.MappedClassBase): ... __tablename__ = u’bovin’ __table_args__ = {‘schema’: ‘cerise’} Définition d’une relation class Bovin(DeclarativeBase, base.MappedClassBase): ... @classmethod def __declare_last__(cls): ‘‘‘ Defines the relations ‘‘‘ from mappers import mother Bovin.mother = sqlalchemy.orm.relation(mother.Mother, lazy=False, uselist=False) Les relations doivent être définie sur un objet pour lequel le mapper a été créé 5
  • 7.
    Définition d’une table Autremanière de définir une relation class Bovin(DeclarativeBase, base.MappedClassBase): ... Bovin.mother = sqlalchemy.orm.relation(Mother, lazy=False, uselist=False) Définition d’un index class Bovin(DeclarativeBase, base.MappedClassBase): ... sqlalchemy.Index( ‘mark_nr_idx’, Bovin.__table__.c.mark_nr) 6
  • 8.
    Définition d’une table Définitiond’une contrainte class Bovin(DeclarativeBase, base.MappedClassBase): ... __tablename__ = u’bovin’ __table_args__ = ( sqlalchemy.CheckConstraint(‘mark_nr != name’, name=’test_constraint’), {‘schema’: ‘cerise’}) # Columns 7
  • 9.
    Activation de laréflexion des tables Modification de la classe DeclarativeBase try: from sqlalchemy.ext.declarative import DeferredReflection except ImportError: from arsia.db.core.declarative import DeferredReflection DeclarativeBase = sqlalchemy.ext.declarative.declarative_base(cls=DeferredReflection) 8
  • 10.
    Méthodes et propriétésde bases mapper_instance.session Renvoi la session associée à l’objet courant ou une nouvelle session mapper_instance.asDict(self) Renvoi l’objet courant sous la forme d’un dictionnaire mapper_instance.clone(self) Renvoi une copie de l’objet courant mapper_instance.update(self, flush=True, commit=False) Met à jour l’objet courant dans la DB mapper_instance.insert(self, flush=True, commit=False) Insert l’objet courant dans la DB mapper_instance.save_or_update(self, flush=True, commit=False) Insert ou met à jour l’objet courant dans la DB 9
  • 11.
    Méthodes et propriétésde base mapper_instance.save mapper_instance.add Aliases de mapper_instance.insert Mapper.exists(cls, **kwargs) Renvoi un booléen si une ligne dans la base de donnée correspond aux filtres données Exemple : Bovin.exists(mark_nr=u’BE12345678’) Mapper.get(cls, **kwargs) Renvoi une liste de résultat qui correspond aux filtres données Exemple d’utilisation : Bovin.get(snun_cde=u’BE12345678-0101’) Mapper.first(cls, **kwargs) Renvoi le premier résultat qui correspond aux filtres données Exemple d’utilisation : Bovin.fist(mark_nr=u’BE12345678’) 10
  • 12.
  • 13.
    Liens JJ I mplémentation dans arsia.db.pgsql : http://svn.arsia.affinitic.be/ Arsia/zope/arsia.db.pgsql/trunk/src/arsia/db/pgsql/mappers/ JJ I mplémentation dans arsia.db.oracle : http://svn.arsia.affinitic.be/ Arsia/zope/arsia.db.oracle/trunk/src/arsia/db/oracle/mappers/ JJ Notre version de SQLAlchemy : http://hg.affinitic.be/sqlalchemy/ JJ Documentation : http://docs.sqlalchemy.org/en/rel_0_7/orm/ extensions/declarative.html 12