33 votes

SQLAlchemy est alambiqué?

Cela peut semble plutôt argumentatif, mais je suis juste allé à travers SQLAlchemy de l' ORM tutoriel et s'est terminé avec le code suivant:

from sqlalchemy import create_engine
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

engine = create_engine('sqlite:///:memory:', echo=True)

metadata = MetaData()
users_table = Table('users', metadata,
    Column('id', Integer, primary_key=True),
    Column('name', String),
    Column('fullname', String),
    Column('password', String)
)

metadata.create_all(engine)

Base = declarative_base()
class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    fullname = Column(String)
    password = Column(String)

    def __init__(self, name, fullname, password):
        self.name = name
        self.fullname = fullname
        self.password = password

    def __repr__(self):
       return "<User('%s','%s', '%s')>" % (self.name, self.fullname, self.password)

users_table = User.__table__
metadata = Base.metadata

Session = sessionmaker(bind=engine)
Session = sessionmaker()
Session.configure(bind=engine)  # once engine is available
session = Session()

# actually using the ORM isn't too bad..
ed_user = User('ed', 'Ed Jones', 'edspassword')
session.add(ed_user)

our_user = session.query(User).filter_by(name='ed').first() 
print our_user

session.add_all([
    User('wendy', 'Wendy Williams', 'foobar'),
    User('mary', 'Mary Contrary', 'xxg527'),
    User('fred', 'Fred Flinstone', 'blah')])

ed_user.password = 'f8s7ccs'

print session.dirty
print session.new
session.commit()

for instance in session.query(User).order_by(User.id): 
    print instance.name, instance.fullname

for name, fullname in session.query(User.name, User.fullname): 
    print name, fullname

Cela semble incroyablement compliqué pour un Hello World table, surtout par rapport à l'à peu près similaire SQLObject code:

from sqlobject import SQLObject, StringCol, sqlhub, connectionForURI

sqlhub.processConnection = connectionForURI('sqlite:/:memory:')

class Person(SQLObject):
    fname = StringCol()
    mi = StringCol(length=1, default=None)
    lname = StringCol()

Person.createTable()

p = Person(fname="John", lname="Doe")
p.mi = 'Q'
p2 = Person.get(1)
print p2
print p2 is p

Je comprends SQLAlchemy est "le plus fort", mais que la puissance semble venir à un coût, ou ai-je raté quelque chose?

86voto

Steven Points 10243

Eh bien, il y a une chose qui vous manque: le tutoriel que vous mentionnez n'est pas "construire" un exemple complet, les différents bouts de code ne sont pas destinés à être concaténés dans un seul fichier source. Plutôt, ils décrivent les différentes manières de la bibliothèque peut être utilisée. Pas besoin d'essayer de faire la même chose encore et encore vous-même.

Laissant de côté le fait-de-la-orm partie de votre exemple, le code pourrait ressembler à ceci:

from sqlalchemy import *
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session

engine = create_engine('sqlite:///:memory:', echo=True)
Base = declarative_base(bind=engine)
Session = scoped_session(sessionmaker(engine))

class User(Base):
    __tablename__ = 'users'

    id = Column(Integer, primary_key=True)
    name = Column(String)
    fullname = Column(String)
    password = Column(String)

Base.metadata.create_all()

Le "déclaratif" extension prend en charge la définition de la table et de la cartographie à votre classe, vous n'avez pas besoin de déclarer l' users_table vous-même. L'Utilisateur de la classe permettra également à l'instanciation avec le mot-clé arguments, comme User(name="foo"), (mais pas les arguments de position tout de même). J'ai aussi ajouté l'utilisation de scoped_session, ce qui signifie que vous pouvez utiliser directement Session sans avoir à instancier (il va instancier une nouvelle session si il n'est pas déjà présent dans le thread en cours, ou la réutilisation de l'existant autrement)

10voto

Jacob Gabrielson Points 8800

Les exemples de code que vous donnez ne sont pas des pommes avec des pommes. La SQLAlchemy version pourrait être réduite vers le bas un peu:

from sqlalchemy import create_engine
from sqlalchemy import Table, Column, Integer, String, MetaData, ForeignKey
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker

engine = create_engine('sqlite:///:memory:', echo=True)
Base = declarative_base()

class User(Base):
    __tablename__ = 'users'

    id = Column('id', Integer, primary_key=True)
    name = Column('name', String)
    fullname = Column('fullname', String)
    password = Column('password', String)

    def __repr__(self):
       return "" % (self.name, self.fullname, self.password)

Base.metadata.create_all(engine)

Session = sessionmaker(bind=engine)
session = Session()

# actually using the ORM isn't too bad..
ed_user = User(name='ed', fullname='Ed Jones', password='edspassword')
session.add(ed_user)

our_user = session.query(User).filter_by(name='ed').first()

session.add_all([
    User(name='wendy', fullname='Wendy Williams', password='foobar'),
    User(name='mary', fullname='Mary Contrary', password='xxg527'),
    User(name='fred', fullname='Fred Flinstone', password='blah')])

ed_user.password = 'f8s7ccs'

session.flush()

for instance in session.query(User).order_by(User.id):
    print instance.name, instance.fullname

for name, fullname in session.query(User.name, User.fullname):
    print name, fullname

Vous pouvez également trouver un Élixir de plus comme SQLObject (mais puisque je n'ai pas utilisé non plus, c'est juste une supposition).

Ne pas avoir utilisé SQLObject à tous, je ne peux pas commenter sur ce que SA fait mieux. Mais j'ai eu de grandes expériences avec SA, surtout lorsqu'il s'agit compliqué, dans le monde réel, les anciens schémas. Il fait un bon travail de venir avec une bonne requêtes SQL par défaut, et il y a beaucoup de façons de les améliorer.

J'ai trouvé SQLAlchemy auteur de l' elevator pitch pour tenir assez bien dans la pratique.

1voto

Nico Points 872

Eh bien, SQLAlchemy est divisé en différentes parties, la base principale de la partie tout simplement les poignées de la DB, en transformant votre python construit des requêtes en langage SQL pour les sous-jacents DB. Ensuite, il ya la prise en charge des sessions, l'orm, et la nouvelle syntaxe déclarative.

Ressemble SQLObject (je ne peux pas dire pour sûr, ne l'ai pas utilisé depuis de nombreuses années, et même alors, seulement une fois) saute plus et ne l'ORM partie tout de suite. Souvent, cela rend les choses plus faciles pour de simples données (que vous pouvez sortir avec dans la plupart des cas), mais SQLAlchemy permet plus complexe db mises en page, et de descendre et sale avec la db si vous en avez vraiment besoin.

1voto

Joe L. Points 1020

Après avoir utilisé SQLObject (et lu uniquement sur SQLAlchemy), je peux dire que l'une des forces de SQLObject est la facilité et la simplicité avec lesquelles vous pouvez faire avancer les choses. En outre, un excellent support est fourni par le groupe de messagerie ( https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss ) qui vous répond assez rapidement.

1voto

Tyler Long Points 1216

Essayez Quick ORM , c'est encore plus simple:

 from quick_orm.core import Database
from sqlalchemy import Column, String

class User(object):
    __metaclass__ = Database.DefaultMeta
    name = Column(String(30))

if __name__ == '__main__':
    database = Database('sqlite://')
    database.create_tables()

    user = User(name = 'Hello World')
    database.session.add_then_commit(user)

    user = database.session.query(User).get(1)
    print 'My name is', user.name
 

L'ORM rapide est construit sur SQLAlchemy, nous pouvons donc dire que SQLAlchemy pourrait être aussi simple que SQLObject.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X