代码之家  ›  专栏  ›  技术社区  ›  dbr

炼金术是复杂的?[闭门]

  •  31
  • dbr  · 技术社区  · 15 年前

    这似乎有点争议,但我刚刚通过了SQLAlchemy ORM tutorial

    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
    

    对于Hello World表来说,这似乎非常复杂,尤其是与大致相似的SQLObject代码相比:

    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
    

    我知道炼金术“更强大”,但这种力量似乎是有代价的,还是我遗漏了什么?

    6 回复  |  直到 12 年前
        1
  •  88
  •   Steven    15 年前

    好吧,有一件事你没有做到:你提到的教程并没有“构建”一个完整的示例,不同的代码片段并不意味着要连接到一个源文件中。相反,它们描述了图书馆的不同使用方式。你不必一次又一次地尝试做同样的事情。

    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(name="foo") 我还添加了scoped_会话的用法,这意味着您可以直接使用 Session 无需实际实例化它(如果当前线程中还没有会话,它将实例化一个新会话,否则将重用现有会话)

        2
  •  10
  •   Jacob Gabrielson    15 年前

    您给出的代码示例并非完全相同。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,我无法评论SA到底做了什么更好。但我在SA方面有着丰富的经验,尤其是在处理复杂的、真实的遗留模式时。默认情况下,它很好地提供了良好的SQL查询,并且有很多方法来优化它们。

    elevator pitch

        3
  •  1
  •   Joe L.    15 年前

    在使用过SQLObject(并且只阅读过SQLAlchemy)之后,我可以说SQLObject的优点之一是可以轻松简单地完成任务。此外,电子邮件组还提供了出色的支持( https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss )这会很快给你答案。

        4
  •  1
  •   Tyler Liu    13 年前

    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
    

    快速ORM

        5
  •  1
  •   Zero Piraeus    11 年前

    好的,SQLAlchemy被分为不同的部分,主要的核心部分只是处理数据库,将python构建的查询转换为底层数据库的适当SQL语言。然后是对会话、orm和新声明语法的支持。

    看起来SQLObject(我不能肯定,已经很多年没有使用过它了,甚至只有一次)跳过了它的大部分,直接完成了ORM部分。这通常会使简单数据的处理变得更容易(在大多数情况下,您可以不受影响),但SQLAlchemy允许更复杂的db布局,如果您确实需要的话,可以直接使用db。

        6
  •  0
  •   Tom Willis    15 年前

    你说“错综复杂”。。。。其他人可能会说“灵活”。有时候你需要,有时候你不需要。你有选择权,这不是很棒吗?