是否有一种在SQLAlchemy之上实现CRUD的规范方法?

时间:2018-03-12 02:40:05

标签: python sqlalchemy crud semantics

我在过去几年中参与了各种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?

0 个答案:

没有答案