目标:创建一个SQLAlchemy属性,该属性跟踪/跟踪另一个对象的SQLAlchemy属性中的更改.
鉴于:
class ClazzA():
attributeA = Column(JSONDict)
class ClazzB():
attributeB = Column(?)
objectA = ClazzA()
objectA.attributeA = {'foo': 1}
objectB = ClazzB()
objectB.attributeB = objectA.attributeA
objectA.attributeA['foo'] = 2
Run Code Online (Sandbox Code Playgroud)
JSONDict与MutableDict此处描述的相关联:http://docs.sqlalchemy.org/en/latest/orm/extensions/mutable.html#module-sqlalchemy.ext.mutable,即该JSONDict类型允许进行突变跟踪.
所以我们在objectA上有这个字典,其变化由SQLAlchemy记录.我希望attributeB跟踪attributeA,这样即使重新启动应用程序(即从DB重新加载属性),attributeB也将继续反映对attributeA字典所做的更改.
当然,这与Python 不知道指针的事实密切相关.我想知道SQLAlchemy是否有针对这个特定问题的解决方案.
你想要一对多的关系.
from sqlalchemy import ForeignKey, Integer, Column
from sqlalchemy.orm import relationship
class Widget(Base):
__tablename__ = 'widget'
widget_id = Column(Integer, primary_key=True)
# name columns, type columns, ...
json = Column(JSONDict)
class ClazzB(Base):
__tablename__ = 'clazzb'
clazzb_id = Column(Integer, primary_key=True)
# Your "attributeB"
widget_id = Column(Integer,
ForeignKey('widget.widget_id',
onupdate='cascade',
ondelete='cascade'),
nullable=False)
widget = relationship('Widget')
# possible association_proxy
#widget_json = association_proxy('widget', 'json')
Run Code Online (Sandbox Code Playgroud)
定义模型和模型之间的关系.既然我们没有全局,下面的定义就是例子.ClazzAClazzB
from sqlalchemy import ForeignKey
from sqlalchemy.orm import relationship
class ClazzA(Base): # replace Base with the base class of your models
__tablename__ = 'clazza' # replace with the real tablename
# T is the type of your primary key, the column name is just an example
clazza_id = Column(T, primary_key=True)
class ClazzB(Base):
# The column that will relate this model to ClazzA
clazza_id = Column(T, ForeignKey('clazza.clazza_id',
onupdate='cascade',
ondelete='cascade'),
nullable=False)
# A handy accessor for relationship between mapped classes,
# not strictly required. Configurable to be either very lazy
# (loaded if accessed by issuing a SELECT) or eager (JOINed
# when loading objectB for example)
objectA = relationship('ClazzA')
Run Code Online (Sandbox Code Playgroud)
现在,而不是添加到参考attributeA的ClazzA,以ClazzB一个参考相关补充objectA到objectB上初始化.
objectB = ClazzB(..., objectA=objectA)
Run Code Online (Sandbox Code Playgroud)
这两个现在是相关的,并通过do 访问attributeA相关objectAobjectB
objectB.objectA.attributeA
Run Code Online (Sandbox Code Playgroud)
无需跟踪更改attributeA,因为它是attributeA实例的更改.
现在,如果你必须有一个属性attributeB上ClazzB(为了避免重构现有的代码或一些这样的),你可以添加一个属性
class ClazzB:
@property
def attributeB(self):
return self.objectA.attributeA
Run Code Online (Sandbox Code Playgroud)
这将返回attributeA相关objectA的
objectB.attributeB
objectB.attributeB['something'] = 'else'
Run Code Online (Sandbox Code Playgroud)
等等.
还有一种用于跨关系访问属性的SQLAlchemy方法:关联代理.它支持简单查询,但不是例如可订阅的.
class ClazzB(Base):
attributeB = association_proxy('objectA', 'attributeA')
Run Code Online (Sandbox Code Playgroud)
如果您希望ClazzB.attributeB从JSONDict某个键下面访问值,您可以使用例如这样的内容
class ClazzB(Base):
key = Column(Unicode)
@property
def attributeB(self):
return self.objectA.attributeA[self.key]
Run Code Online (Sandbox Code Playgroud)
如果需要这样的话,您还可以attributeB使用混合属性在类级别上作为SQL表达式工作.您必须自己编写类级表达式.
| 归档时间: |
|
| 查看次数: |
171 次 |
| 最近记录: |