我曾问过这个问题How to create instance of a table entry but not added in ponyorm?,当时我在问我如何创建不定义为ponyorm表表示形式的类的实例,而无需立即添加它。通过使用在add
实例上需要显式session
的sqlalchemy,我认为我通过使用以下代码成功了。
我首先创建一个名为AddInstance
的类,该类具有一个add方法,然后在我的所有表定义中从该类继承。这似乎可行(即,我可以创建该类的实例,并且仅在我想相对轻松的情况下才添加它),但是我不确定是否有任何意外的副作用,或者这与最佳实践相去甚远。
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy import Column, String, Integer
engine = create_engine('sqlite:///:memory:')
Base = declarative_base()
Session = sessionmaker(bind=engine)
class AddInstance:
def add(self):
session = Session()
session.add(self)
session.commit()
class Pizza(Base, AddInstance):
__tablename__ = 'pizzas'
id = Column(Integer, primary_key=True)
name = Column(String(50))
toppings = relationship('Topping', back_populates='name')
class Topping(Base, AddInstance):
__tablename__ = 'fruits'
id = Column(Integer, primary_key=True)
name = Column(String(50))
pizzas = relationship('Pizza', back_populates='name')
Base.metadata.create_all(engine)
答案 0 :(得分:2)
没有副作用,SQLAlchemy明确支持添加方法。那些方法是在mixin类上定义还是直接在从Base
派生的类上定义都没关系。
引用SQLAlchemy Object Relational Tutorial documentation section:
除了对我们的类进行映射的过程之外,该类仍然是其他大多数普通的Python类,我们可以为该类定义应用程序所需的任意数量的普通属性和方法。 >
(粗体重点)。
有许多完全相同的代码库示例。 Flask-SQLAlchemy为add a query
attribute提供了Model
基类(在declarative base is created时设置),例如,您可以直接从模型类中进行Topping.query(...)
。
您的add()
方法确实有缺点:它创建了一个新的Session()
实例,仅用于添加和提交对象。这使它不属于常规session state management semantics,如果您想对新创建的对象做其他任何操作,则必须merge it into an existing session。
涉及SQLAlchemy对象的代码的通常的最佳实践是创建一个会话来管理事务,这是一组必须成功或失败的操作。这包括创建对象;在许多实际应用程序中,当依赖于那些行的其他操作失败时,您希望避免在数据库中创建多余的行。您的.add()
方法无条件地在单独的事务中提交每个对象。您可能需要重新访问此模式。