我在过去几年中参与了各种SQLAlchemy项目,但这意味着CRUD已经以不同的方式完成了:
在许多情况下,定义声明性模型的模块将包括委托CRUD的函数(读取:不是模型方法;只是模块级函数),例如:
class Foo(Base):
bar = Column(String)
def create_foo(bar):
with Session() as sess:
try:
sess.add(Foo(bar=bar))
return sess.commit()
except IntegrityError:
sess.rollback()
raise
# ... and so on...
这些基本上是来自SQLAlchemy的文档的查询API调用,包含在一些会话管理代码中并委托给函数。
这里明显的缺点是定义单个模型的CRUD需要大量的开销,大量的代码重复,特别是如果你有很多模型,并且缺乏优雅,特别是在例外处理中。
在某些情况下,我已经看到为某些CRUD操作实现了装饰器:
from contextlib import contextmanager
@contextmanager
def session_scope():
"""Provide a transactional scope around a series of operations."""
session = Session()
try:
yield session
session.commit()
except:
session.rollback()
raise
finally:
session.close()
def safe_session(func):
with session_scope() as sess:
def wrapper(*args, **kwargs):
func(sess, *args, **kwargs)
@safe_session
def create_foo(session, bar):
session.add(Foo(bar=bar))
虽然这种方法相当一致(在灵活性和稳定性方面),但我还没有经常看到它的实现,所以我在代码库中使用它时要谨慎,因为它可能会在& #34;怪异"或"非标准。"
最后,除了CRUD
生成的类之外,还有another question and answer here显示如何使用declarative_base()
超类的多重继承来实现类似于Django和Rails的ActiveRecord模式:
# SQLAlchemy db_session setup omitted
...
Model = declarative_base(name='Model')
Model.query = db_session.query_property()
class CRUD():
def save(self):
if self.id == None:
db_session.add(self)
return db_session.commit()
def destroy(self):
db_session.delete(self)
return db_session.commit()
class User(Model, CRUD):
__tablename__ = 'users'
id = db.Column(db.integer, primary_key=True)
email = db.Column(db.String(120), unique=True)
def __init__(self, email):
self.email = email
...但这最多是模糊的,并且使类定义语义有点尴尬,可能在构造函数中有一堆错误处理。
这三个"主要"在SQLAlchemy上执行CRUD的方法(可能还有许多其他可用的和未列出的),这在语义上是最正确的吗?
是否有一些其他的,语义更正确(甚至是规范)的方式来执行此处未列出的CRUD?