我有一个Flask python应用程序,它有一组通过外键链接在一起的相关表。我希望能够从一个表中返回与远程表相关的记录的聚合列表。但是,我正在努力理解sqlalchemy如何通过对象关系来实现这一点。
例如,有三个我想加入的对象(挑战和徽章),有两个表(talent_challenge和徽章),可以查询与特定挑战相关的所有徽章。在SQL中,这看起来像:
SELECT b.id, b.name
FROM badge b
INNER JOIN talent_challenge tc ON tc.talent_id = b.talent_id
WHERE tc.challenge_id = 21
在这种情况下,不需要'才能'和'挑战'表,因为我只需要人才和挑战ID(在'talent_challenge'中)用于关系。所有有趣的细节都在徽章表中。
我可以使用sqlalchemy通过以下方式从挑战中获取相关人才:
talents = db.relationship('TalentModel', secondary='talent_challenge')
然后我可以参考talent.badges
获取每个人才,以获得与我最初的挑战相关的相关徽章。但是,可能存在冗余,并且此徽章列表不包含在单个对象中。
这三个模型的精简版本是:
class TalentModel(db.Model):
__tablename__ = 'talent'
# Identity
id = db.Column(db.Integer, primary_key=True)
# Relationships
challenges = db.relationship('ChallengeModel', secondary='talent_challenge',)
# badges (derived as backref from BadgeModel)
class ChallengeModel(db.Model):
__tablename__ = 'challenge'
# Identity
id = db.Column(db.Integer, primary_key=True)
member_id = db.Column(db.Integer, db.ForeignKey('member.id'))
# Relationships
talents = db.relationship('TalentModel', secondary='talent_challenge', order_by='desc(TalentModel.created_at)')
class BadgeModel(db.Model):
__tablename__ = 'badge'
# Identity
id = db.Column(db.Integer, primary_key=True)
talent_id = db.Column(db.Integer, db.ForeignKey('talent.id'))
# Parents
talent = db.relationship('TalentModel', foreign_keys=[talent_id], backref="badges")
我还有一个关联表模型'talent_challenge':
class TalentChallengeModel(db.Model):
__tablename__ = 'talent_challenge'
# Identity
id = db.Column(db.Integer, primary_key=True)
talent_id = db.Column(db.Integer, db.ForeignKey('talent.id'))
challenge_id = db.Column(db.Integer, db.ForeignKey('challenge.id'))
# Parents
talent = db.relationship('TalentModel', uselist=False, foreign_keys=[talent_id])
challenge = db.relationship('ChallengeModel', uselist=False, foreign_keys=[challenge_id])
我想更好地理解sqlalchemy(或者具体来说,flask-sqlalchemy),以允许我从挑战对象构建这个徽章列表。 BadgeModel的db.session.query
是我唯一的选择吗?
2015年1月23日更新: 我的项目中的阻止程序通过使用以下内容解决:
@property
def badges(self):
from app.models.sift import BadgeModel
from app.models.relationships.talent import TalentChallengeModel
the_badges = BadgeModel.query\
.join(TalentChallengeModel, TalentChallengeModel.talent_id==BadgeModel.talent_id)\
.filter(TalentChallengeModel.challenge_id==self.id)\
.all()
return the_badges
在一个函数中包装查询解决了我所遇到的问题{名称BadgeModel
未被定义,否则无法在模型中导入。 @property
装饰器允许我稍后在视图中将其引用为challenge.badges
。
但是,我仍然有兴趣了解如何将此作为一种关系。一些在别处搜索让我相信这会起作用:
badges = db.relationship('BadgeModel',
secondary="join(BadgeModel, TalentChallengeModel, BadgeModel.talent_id == TalentChallengeModel.talent_id)",
secondaryjoin="remote([id]) == foreign(TalentChallengeModel.challenge_id)",
primaryjoin="BadgeModel.talent_id == foreign(TalentChallengeModel.talent_id)",
viewonly=True,
)
由于我的应用程序环境中存在其他未解决的问题,我无法对此进行全面测试(例如,在我的网站中添加此代码会破坏Flask-User)但是想知道这是否是正确的语法以及是否存在任何缺点通过函数查询解决方案。