查询时设置非ORM对象字段

时间:2017-10-27 06:13:46

标签: python python-3.x sqlalchemy

假设我有一个班级Interaction。我的程序以每个交互更新分数表的方式处理interactionsInteraction被声明为数据库表的精确映射,但我也希望它引用ScoreTable的相关实例。 ScoreTable是一个包含分数的类,并控制业务逻辑以更新分数:

class Interaction(Base):
    __tablename__ = 'interactions'
    #Mirror the table's structure
    anomaly_id = Column(Integer, ForeignKey('anomalies.id'), primary_key=True)
    user_id = Column(Integer, primary_key=True) # ForeignKey('users.id'),
    feedback_score = Column(Integer)

    #scoreUpdater is another (non-ORM) object I want this instance to be aware of
    myScoreUpdater=  ...

Interaction提取的query()的所有实例都将共享相同的ScoreUpdater。因此,当我运行query()以获取Interactions的所有实例时,我能以某种方式告诉query()scoreUpdater设置为某个值,在同一个进程中吗?另外,如果query()克隆并填充ORM数据,我可以给Interaction半建模板实例吗? 我读过我可以修改标准构造函数来执行某些任务,但不知道如何通过query()

将额外的参数(例如ScoreUpdater的实例)传递给构造函数

我想另一种方法是首先运行query并让它填充与ORM相关的字段,然后在第二步中迭代查询结果以设置非OM字段(即rightUpdater的正确实例)?

我是SQLalchemy的新手......并且从java转换为python。所以如果你认为我的方法根本就错了,请告诉我!

1 个答案:

答案 0 :(得分:1)

相关的documentation on constructing objects说:

  

从数据库行重新创建对象时,SQLAlchemy ORM不会调用__init__。 ORM的过程有点类似于Python标准库的pickle模块,调用低级__new__方法,然后直接在实例上静默恢复属性,而不是调用__init__

     

如果你需要在数据库加载的实例准备好使用它们之前做一些设置,那么有一个名为InstanceEvents.load()的事件挂钩可以实现这一点;它也可以通过名为orm.reconstructor()的特定于类的装饰器获得。使用orm.reconstructor()时,映射器将在每次加载或重构类的实例时调用没有参数的修饰方法。这对于重新创建通常在__init__

中指定的瞬态属性非常有用

因此,如果我已正确理解您,您可以为Interaction定义一个填充非ORM字段的重构器:

from sqlalchemy.orm import reconstructor

class Interaction(Base):

    __tablename__ = 'interactions'

    # Mirror the table's structure
    anomaly_id = Column(Integer, ForeignKey('anomalies.id'), primary_key=True)
    user_id = Column(Integer, primary_key=True) # ForeignKey('users.id'),
    feedback_score = Column(Integer)

    # myScoreUpdater is another (non-ORM) object I want this instance to be aware of
    @reconstructor
    def init_on_load(self):
        # Do what you must to populate score updater
        self.myScoreUpdater =  ...

请注意,您可能希望在重构器和__init__之间共享逻辑,因此只需将__init__装饰为重构器,如果可以不带参数调用,或者移动初始化得分更新者的方法。

最后,如果你的ScoperUpdater实际上不需要知道它绑定到哪个实例,你可以将它作为所有实例之间共享的类属性 - 比如Java中的静态属性。