Python 从子对象查询项目

Python 从子对象查询项目,python,flask,sqlalchemy,Python,Flask,Sqlalchemy,我有一个flaskpython应用程序,它有一组通过外键链接在一起的相关表。我希望能够从一个表返回与远程表相关的记录的聚合列表。然而,我很难理解sqlalchemy是如何通过对象关系实现这一点的 例如,我希望将三个对象(挑战和徽章)与两个表(talent_挑战和徽章)连接起来,以便能够查询与特定挑战相关的所有徽章。在SQL中,这类似于: SELECT b.id, b.name FROM badge b INNER JOIN talent_challenge tc ON tc.talent_id

我有一个flaskpython应用程序,它有一组通过外键链接在一起的相关表。我希望能够从一个表返回与远程表相关的记录的聚合列表。然而,我很难理解sqlalchemy是如何通过对象关系实现这一点的

例如,我希望将三个对象(挑战和徽章)与两个表(talent_挑战和徽章)连接起来,以便能够查询与特定挑战相关的所有徽章。在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(在“人才挑战”中)。所有有趣的细节都在徽章表中

我能够使用sqlalchemy通过以下方式从挑战中获得相关天赋:

talents = db.relationship('TalentModel', secondary='talent_challenge')
然后我可以为每一个天赋引用
天赋。徽章
,以获得与我最初挑战相关的徽章。但是,可能存在冗余,并且此徽章列表不包含在单个对象中

这三种型号的精简版为:

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")
我还有一个关联表“人才挑战”的模型:

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(或者特别是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
未定义以及无法在模型中导入的问题。
@属性
装饰器允许我稍后在视图中将其作为
挑战.徽章
引用

然而,我仍然有兴趣了解如何作为一种关系做到这一点。其他地方的一些搜索让我相信这会奏效:

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,
    )
由于我的应用程序环境中存在其他未解决的问题,我无法完全测试这一点(例如,在我的站点中添加此代码),但我想知道这是否是正确的语法,以及与函数解决方案中的查询相比,这是否有任何缺点