Вопрос

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

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

Это было полезно?

Решение

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

Если исключить из вашего примера часть фактического использования орма, код может выглядеть следующим образом:

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

Другие советы

Примеры кода, которые вы приводите, не являются «яблоками к яблокам».Версию 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

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

Вообще не используя SQLObject, я не могу прокомментировать, что именно SA делает лучше.Но у меня большой опыт работы с SA, особенно когда я имел дело со сложными, реальными устаревшими схемами.По умолчанию он хорошо справляется с созданием хороших SQL-запросов и имеет множество способов их настройки.

Я нашел авторскую книгу SQLAlchemy лифтовая площадка довольно хорошо держаться на практике.

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

Пытаться Быстрый ОРМ, это еще проще:

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

Быстрый ОРМ построен на основе SQLAlchemy, поэтому можно сказать, что SQLAlchemy может быть таким же простым, как SQLObject.

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top