1

好的,所以我正在尝试编写代码,让我们扩展类以具有“属性”或元数据键值对。例如在我的应用程序中,我想将它用于

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)
4

0 回答 0