Подтвердить что ты не робот

SQLAlchemy запутан?

Это может показаться довольно спорным, но я просто прошел через 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

Это кажется невероятно сложным для эффективной таблицы 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

Я понимаю, что SQLAlchemy "более мощный", но эта власть, кажется, стоит дорого или я что-то не хватает?

4b9b3361

Ответ 1

Ну, есть одна вещь, которую вам не хватает: упомянутый вами учебник не "строит" полный пример, разные фрагменты кода не предназначены для конкатенации в один исходный файл. Скорее, они описывают различные способы использования библиотеки. Не нужно пытаться повторять то же самое снова и снова.

Оставив часть примера с помощью примера, код может выглядеть так:

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, не имея при этом необходимости создавать его (он будет создавать новый сеанс, если в текущем потоке уже нет ни одного присутствующего, или повторно использовать существующее в противном случае )

Ответ 2

Приведенные примеры кода не являются яблоками для яблок. Версия 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 шаг лифта, чтобы хорошо сохраниться на практике.

Ответ 3

Ну, SQLAlchemy делится на разные части, основная часть ядра просто обрабатывает БД, преобразуя ваши построенные на Python запросы в соответствующий язык SQL для базовой БД. Затем есть поддержка сессий, orm и новый декларативный синтаксис.

Похож на SQLObject (я не могу сказать точно, не использовал его за многие годы, и даже тогда, только один раз) пропускает большую часть его и немедленно выполняет ORM. Это часто упрощает простые данные (в большинстве случаев их можно избежать), но SQLAlchemy позволяет создавать более сложные макеты db и сбрасывать их с db, если вам это действительно нужно.

Ответ 4

Используя SQLObject (и только читать о SQLAlchemy), я могу сказать, что одна из сильных сторон SQLObject - это простота и простота, с которыми вы можете добиться результата. Кроме того, отличная поддержка предоставляется группой электронной почты (https://lists.sourceforge.net/lists/listinfo/sqlobject-discuss), которая быстро получает ответы на ваши вопросы.

Ответ 5

Попробуйте Быстрый 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 построен на SQLAlchemy, поэтому мы можем сказать, что SQLAlchemy может быть так же просто, как SQLObject.

Ответ 6

вы говорите "запутанный".... кто-то другой может сказать "гибкий". Иногда вам это нужно, иногда вы этого не делаете. Разве это не удивительно, что у вас есть выбор?