好的,所以我正在尝试编写代码,让我们扩展类以具有“属性”或元数据键值对。例如在我的应用程序中,我想将它用于
obj.color = 'test"
但它给了我一个递归错误
File "/home/ekarlso/bookie-frontend/bookie/models/base.py", line 96, in __getattr__
if is_instrumented(self, key):
File "/home/ekarlso/venv/lib/python2.6/site-packages/sqlalchemy/orm/instrumentation.py", line 460, in is_instrumented
return manager_of_class(instance.__class__).\
RuntimeError: maximum recursion depth exceeded
我尝试__getattr__
按照
https://bitbucket.org/zzzeek/sqlalchemy-2208/src/f9fac8a6cc88/custom_management.py进行覆盖,
但它不起作用,有人对修复实现有一些线索吗?
from sqlalchemy.orm import class_mapper, object_mapper, scoped_session, sessionmaker
from sqlalchemy.orm.attributes import set_attribute, get_attribute, del_attribute
from sqlalchemy.orm.instrumentation import is_instrumented
class MetadataMixin(object):
"""
Mixin to extend a class with attributes / info in a related table
"""
__meta_attr__ = "metadata"
def meta_set(self, meta, cls=None):
"""
Create or update metadata for an Entity
:param meta: Metadata to be set
"""
meta_cls = object_mapper(self).get_property(self.meta_attr(cls)).\
mapper.class_
meta_current = self.meta_dict(cls=cls)
for key, value in meta.items():
values = {"entity_id": self.id, "key": key, "value": value}
if key in meta_current:
meta_ref = meta_current[key]
else:
meta_ref = meta_cls()
meta_ref.from_dict(values)
meta_ref.save()
return self
def meta_get(self, key, cls=None):
"""
Get metadata based on key
:param key: The key to get
"""
meta_ref = self.meta_dict(cls=cls).get(key, None)
return meta_ref.value if meta_ref else meta_ref
def meta_delete(self, key):
meta = self.meta_get(key).delete()
def meta_dict(self, cls=None):
"""
Return metadata as a dict
"""
meta_attr = getattr(self, self.meta_attr(cls=cls))
return dict([(m.key, m) for m in meta_attr])
def meta_attr(self, cls=None):
"""
This returns the attribute which other methods act upon
"""
return cls or self.__meta_attr__
def __setattr__(self, key, value):
if is_instrumented(self, key):
set_attribute(self, key, value)
else:
self.set_meta({name: value})
def __getattr__(self, key):
if is_instrumented(self, key):
return get_attribute(self, key)
else:
return self.meta_by_key(key)
def __delattr__(self, key):
if is_instrumented(self, key):
del_attribute(self, key)
else:
self.meta_delete(self, name)