是否可以在关联代理中更改引用的集合类的键?
示例:
class Event(ManagerBase):
"""Defines an event."""
__tablename__ = 'eventing_events'
id = Column(Integer, primary_key=True)
device_id = Column(Integer, ForeignKey(EventingDevice.id), nullable=False)
device = relation(EventingDevice)
type_id = Column(Integer, ForeignKey(EventType.id), nullable=False)
type = relation(EventType)
datetime = Column(DateTime, nullable=False)
summary = Column(String(500))
fields = association_proxy("field_values", "value")
class EventFieldValue(ManagerBase):
"""The value of a single field of an event."""
__tablename__ = 'eventing_event_field_values'
event_id = Column(Integer, ForeignKey(Event.id), primary_key=True)
event = relation(Event, backref=backref("field_values",
collection_class=attribute_mapped_collection("field")))
field_id = Column(Integer, ForeignKey(Field.id), primary_key=True)
field = relation(Field)
value = Column(Text)
在这种情况下,field
的{{1}}属性将代表以Event
为关键字的字典。是否可以仅在代理本身中更改此密钥而不影响关联?
答案 0 :(得分:1)
似乎原始SQLAlchemy AssociationProxy
无法实现这一点,因为类直接访问原始关系,因此任何键都将在基础关系上以1:1查询。
我写了一个类DictProxy
,它允许更改键和值字段:
class DictProxy(object):
def __init__(self, col, keyattr, valattr = None):
self.obj = None
self.col = col
self.keyattr = keyattr
self.valattr = valattr
def __get__(self, obj, class_):
self.obj = obj
return self
def __repr__(self):
outdict = {}
for k, v in getattr(self.obj, self.col).iteritems():
if not k is None:
if self.valattr == None:
outdict[getattr(k, self.keyattr)] = v
elif v is not None:
outdict[getattr(k, self.keyattr)] = getattr(v, self.valattr)
else:
outdict[getattr(k, self.keyattr)] = None
return repr(outdict)
def __getitem__(self, key):
keyobj = [obj for obj in getattr(self.obj, self.col) if getattr(obj, self.keyattr) == key]
if not len(keyobj):
return None
if self.valattr == None:
return getattr(self.obj, self.col)[keyobj[0]]
else:
return getattr(getattr(self.obj, self.col)[keyobj[0]], self.valattr)
def __contains__(self, key):
return len([obj for obj in getattr(self.obj, self.col) if getattr(obj, self.keyattr) == key]) != 0
def dict_proxy(*arg):
return DictProxy(*arg)
使用示例:
class Event(ManagerBase):
"""Defines an event."""
__tablename__ = 'eventing_events'
id = Column(Integer, primary_key=True)
device_id = Column(Integer, ForeignKey(EventingDevice.id), nullable=False)
device = relation(EventingDevice)
type_id = Column(Integer, ForeignKey(EventType.id), nullable=False)
type = relation(EventType)
datetime = Column(DateTime, nullable=False)
summary = Column(String(500))
fields = dict_proxy("field_values", "name", "value")
fields
的{{1}}现在是一个以Event
为关键字的字典,并访问关系field_values(来自EventFieldValue.name
来自EventFieldValue
)。
注意:强>
实际上这是一个只读代理,但是可能(尽管很棘手)通过backref
方法扩展代理。