36

これはかなり議論の余地があるように思えるかもしれませんが、SQLAlchemy のORM チュートリアルを実行したところ、次のコードになりました。

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

これは、特にほぼ同様の SQLObject コードと比較すると、実質的に Hello World テーブルにとって信じられないほど複雑に見えます。

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

SQLAlchemy が「より強力」であることは理解していますが、その力には代償が伴うようですが、それとも何か不足しているのでしょうか?

4

6 に答える 6

88

さて、あなたが見逃していることが1つあります.あなたが言及しているチュートリアルは完全な例を「構築」していません.コードのさまざまなスニペットは、1つのソースファイルに連結されることを意図していません. むしろ、ライブラリを使用できるさまざまな方法について説明しています。自分で何度も同じことを試す必要はありません。

例から実際に orm を使用する部分を除外すると、コードは次のようになります。

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()

「宣言型」拡張機能は、テーブルの定義とクラスへのマッピングを処理するため、自分自身を宣言する必要はありませんusers_table。User クラスでは、 , などのキーワード引数を使用してインスタンス化することもできますUser(name="foo")(ただし、位置引数は使用できません)。また、scoped_session の使用も追加しました。これは、Session実際にインスタンス化する必要なく直接使用できることを意味します (現在のスレッドにセッションがまだ存在しない場合は新しいセッションをインスタンス化し、それ以外の場合は既存のセッションを再利用します)。

于 2009-05-13T21:52:41.983 に答える
10

あなたが与えるコード例は、りんごとりんごではありません。SQLAlchemy のバージョンは少し削減できます。

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

また、 Elixirは SQLObject に似ていると感じるかもしれません(ただし、どちらも使用したことがないため、これは推測にすぎません)。

SQLObject をまったく使用したことがないので、SA の何が優れているのかについてコメントすることはできません。しかし、私は SA で素晴らしい経験をしてきました。特に、複雑で実世界のレガシー スキーマを扱う場合はそうです。デフォルトで優れた SQL クエリを作成し、それらを調整する方法がたくさんあります。

私は、SQLAlchemy の著者のエレベーター ピッチが実際にうまく機能することを発見しました。

于 2009-05-13T21:53:11.920 に答える
1

さて、SQLAlchemy はさまざまな部分に分かれています。主要なコア部分は単に DB を処理し、Python で構築されたクエリを基礎となる DB に適した SQL 言語に変換します。次に、セッション、orm、および新しい宣言構文のサポートがあります。

SQLObject のように見えます (確かなことは言えませんが、何年も使用しておらず、それでも 1 回しか使用していません) は、そのほとんどをスキップして、ORM の部分をすぐに実行します。これにより、多くの場合、単純なデータの処理が容易になります (ほとんどの場合、これで解決できます) が、SQLAlchemy では、より複雑なデータベース レイアウトが可能であり、本当に必要な場合はデータベースを使いこなすことができます。

于 2009-05-13T21:05:04.620 に答える
1

SQLObject を使用した (そして SQLAlchemy についてしか読んだことがない) ことから、SQLObject の強みの 1 つは、作業を簡単かつ単純に実行できることだと言えます。また、メール グループ ( https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss ) によって優れたサポートが提供され、回答がすぐに返されます。

于 2009-05-13T22:04:53.383 に答える
1

Quick ORMを試してみてください。さらに簡単です。

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

Quick ORMは SQLAlchemy に基づいて構築されているため、SQLAlchemy は SQLObject と同じくらい単純であると言えます。

于 2011-11-11T18:53:42.600 に答える
0

あなたは「入り組んだ」と言います....他の誰かが「柔軟」と言うかもしれません。必要な場合と必要でない場合があります。選べるってすごいじゃないですか。

于 2009-05-13T20:58:36.487 に答える