5

我在模型中设置了以下关系:

role_profiles = Table('roleprofile', Base.metadata,
                  Column('role_id', Integer, ForeignKey('role.id')),
                  Column('profile_id', Integer, ForeignKey('profile.id'))
                  )

class profile(Base):
    __tablename__ = 'profile'

    # Columns...

    roles = relationship('role', secondary=role_profiles, backref='profiles')


class role(Base):
    __tablename__ = 'role'

    # Columns...

因此,据我所知,它的工作原理是配置文件对象上的角色属性将包含角色类列表(它确实如此)。

我想要做的是一般地为模型类的每个属性序列化。它适用于顶级配置文件,我确定有一个roles我应该递归到的列表:

# I need a statement here to check if the field.value is a backref
#if field.value is backref:
#    continue

if isinstance(field.value, list):
    # Get the json for the list
    value = serialize.serialize_to_json(field.value)
else:
    # Get the json for the value
    value = cls._serialize(field.value)

问题是backref关系的 增加了一个指向配置文件的指针。然后对相同的配置文件进行序列化,并一遍又一遍地递归角色,直到stack overflow.

有没有办法确定该属性是由 abackref添加的relationship

更新

也许我应该补充一点,如果我删除它,它在这种情况下可以正常工作,backref因为我不需要它,但我想保留它。

更新

作为临时修复,我在基类中添加了一个类属性:

class BaseModelMixin(object):
    """Base mixin for models using stamped data"""

    __backref__ = None

并像这样添加它:

class role(Base):
    __tablename__ = 'role'
    __backref__ = ('profiles', )

    # Columns...

并在我的递归中像这样使用它:

if self.__backref__ and property_name in self.__backref__:
    continue

如果有更好的方法,请告诉我,因为这看起来不是最佳的。

4

3 回答 3

3

不确定这是否是最佳实践,但这段代码对我有用。如果属性是引用,则返回 True,如果是常规列类型,则返回 False。

def is_relation(orm_object, attr_name):
    return hasattr(getattr(orm_object.__class__, attr_name).property, 'mapper')
于 2016-04-21T15:48:11.943 回答
3

__relationships__您可以在您的类中创建 aBaseModelMixin作为 a @property,其中包含所有关系名称的列表,这些名称不是模型中的 backref 名称。

class BaseModelMixin(object):
"""Base mixin for models using stamped data"""

    @property
    def __relationships__(self):  
        """
        Return a list of relationships name which are not as a backref
        name in model    
        """
        back_ref_relationships = list()
        items = self.__mapper__.relationships.items()
        for (key, value) in items:
            if isinstance(value.backref, tuple):
                back_ref_relationships.append(key)
        return back_ref_relationships

因为你有两个班级profilerole所以

>>> p = profile()
>>> p.__relationships__
    # ['roles']

>>> r = role()
>>> r.__relationships__
   # []
于 2015-10-06T18:56:21.257 回答
2

看一下inspect

例如

from sqlalchemy import inspect
mapper = inspect(MyModelClass)
# dir(mapper)
# mapper.relationships.keys()
于 2013-08-09T07:38:05.937 回答