确定属性是否为sqlalchemy中的backref

时间:2013-08-08 13:25:41

标签: python sqlalchemy

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

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属性将包含一个角色类列表(它所做的)。

我想要做的是一般地为模型类的每个属性序列化。它适用于顶级类配置文件,我确定有一个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

有没有办法确定该属性是backref添加的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

如果有更好的方法请告诉我,因为这看起来并不理想。

3 个答案:

答案 0 :(得分:3)

您可以在班级__relationships__中创建BaseModelMixin作为@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__
   # []

答案 1 :(得分:3)

不确定这是否是最佳做法,但此代码适用于我。如果属性是引用,则返回True;如果是常规列类型,则返回False。

def is_relation(orm_object, attr_name):
    return hasattr(getattr(orm_object.__class__, attr_name).property, 'mapper')

答案 2 :(得分:2)

查看inspect

e.g。

from sqlalchemy import inspect
mapper = inspect(MyModelClass)
# dir(mapper)
# mapper.relationships.keys()