在sqlalchemy中将方法添加到decerative类是否有任何副作用?

时间:2018-11-03 13:22:00

标签: python sqlalchemy

我曾问过这个问题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)                                                   

1 个答案:

答案 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()方法无条件地在单独的事务中提交每个对象。您可能需要重新访问此模式。