如何实现自我引用的多对多关系,这种关系实际上是两个其他关系的结合?
该关系应返回用户与网络中其他用户之间存在的所有FacebookFriendship模型。用户可能拥有指向另一个现有用户的FacebookFriendship,但由于FB API中断,隐私控制等,现有用户可能不存在镜像FBFriendship给该用户。
# This class is necessary for python-social-auth
# A UserSocialAuth model only exists for users who are in the network
class UserSocialAuth(_AppSession, Base, SQLAlchemyUserMixin):
"""Social Auth association model"""
__tablename__ = 'social_auth_usersocialauth'
__table_args__ = (UniqueConstraint('provider', 'uid'),)
id = Column(Integer, primary_key=True)
provider = Column(String(32))
uid = Column(String(UID_LENGTH))
extra_data = Column(JSONType())
user_id = Column(
Integer, ForeignKey(User.id), nullable=False, index=True)
user = relationship(
User,
backref=backref('social_auth', lazy='dynamic')
)
此关系发现FacebookFriendship模型指向此用户指向任何现有用户。
facebook_friendships = relationship(
FacebookFriendship,
primaryjoin=and_(
user_id == FacebookFriendship.user_id,
provider == 'facebook'
),
secondary=FacebookFriendship.__table__,
secondaryjoin=uid == FacebookFriendship.fb_uid_friend,
foreign_keys=[provider, user_id, uid],
viewonly=True,
uselist=True,
lazy='dynamic',
)
此关系找到指向此用户的FacebookFriendship模型。
other_facebook_friendships = relationship(
FacebookFriendship,
primaryjoin=and_(
uid == FacebookFriendship.fb_uid_friend,
provider == 'facebook'
),
foreign_keys=[provider, uid],
viewonly=True,
uselist=True,
lazy='dynamic',
)
我能够使用hybrid_property装饰器来表达联合查询,但是这可以防止像any()或使用关联代理这样的比较器的使用,至少从我能说的就是这样。
# Can I rewrite this using relationship()?
@hybrid_property
def all_facebook_friendships(self):
return self.facebook_friendships.union(
self.other_facebook_friendships).correlate(
FacebookFriendship)
# FBFriendship models are created for every friend that a user has,
# regardless of whether they're in the network or not.
class FacebookFriendship(Base):
__tablename__ = u'user_fb_friend'
user_id = Column(Integer, sa.ForeignKey(User.id), primary_key=True)
user = relationship(
User, backref=backref('facebook_friendships', lazy='dynamic'),
primaryjoin=User.id == user_id)
fb_uid_friend = Column(sa.String(length=255), primary_key=True)
最后,我想像任何其他InstrumentedAttribute一样查询这种关系:
UserSocialAuth.query.filter(UserSocialAuth.all_facebook_friendships.any()).all()
并在User模型上定义association_proxy:
User.all_facebook_friends = association_proxy('all_facebook_friendships', 'user')
对不起这个问题的篇幅,但我已经试过了。现在几天都没有用了。
相关:
答案 0 :(得分:0)
使用上面链接的zzzeek解决方案,我使用select语句作为" secondary"创建了一个自引用的M2M关系。关系()的论据。
friendship_union = select([
FacebookFriendship.dater_id,
cast(FacebookFriendship.fb_uid_friend, Integer()).label(
'fb_uid_friend')
]).union(
select([
cast(FacebookFriendship.fb_uid_friend, Integer()),
FacebookFriendship.dater_id]
)
).alias()
cls.all_fb_friendships = relationship(
UserSocialAuth,
secondary=friendship_union,
primaryjoin=UserSocialAuth.user_id == friendship_union.c.dater_id,
secondaryjoin=and_(
UserSocialAuth.provider == 'facebook',
cast(UserSocialAuth.uid, Integer() ) == friendship_union.c.fb_uid_friend,
),
viewonly=True
)