如何在sqlalchemy中从父母那里获得孩子的孩子?

时间:2014-11-05 16:13:19

标签: python sqlalchemy flask-sqlalchemy

假设我有一份礼物,每件礼物都有一个子类别“即香水”,每个子类别都属于一个类别“即女性礼物”(换句话说,就像在URL中一样:“/ female-礼品/香水/ foo-gift“或”男士礼品/香水/酒吧礼品“)

class Category(db.Model):
    __tablename__ = 'category'

    id = db.Column(db.String(32), primary_key=True)
    name = db.Column(db.String(40), unique=True)
    sub_categories = db.relationship("SubCategory", backref="category")

class SubCategory(db.Model):
    __tablename__ = 'sub_category'

    id = db.Column(db.String(32), primary_key=True)
    name = db.Column(db.String(40), primary_key=True)
    category_id = db.Column(
        db.String(32), db.ForeignKey('category.id'), primary_key=True)

class Gift(db.Model):
    __tablename__ = 'gift'

    id = db.Column(db.String(5), primary_key=True)
    sub_category_id = db.Column(
        db.String(32), db.ForeignKey('sub_category.id'))
    sub_category = db.relationship(SubCategory, uselist=False, backref='gifts')
    category = # WHAT SHOULD I WRITE HERE???

我希望通过这些陈述获得“非子类别”类别中的所有礼物:

Gift.query.filter_by(category_id='1234').all()

Category.query.filter_by(id='1234').first().gifts

以上陈述将返回相同的结果

我的问题是:如何在“类内”配置这些关系以使上述语句有效?

谢谢:)

1 个答案:

答案 0 :(得分:1)

选项-1:简单查询

虽然您可以轻松完成此操作,但我不建议您使用此jump - relationship,因为它是readonly,您或您的用户可能忘记

将这两者创建为查询非常容易:

# parameters
category_id = '1234'

# query-1:
q = Gift.query.join(SubCategory).filter(SubCategory.category_id == category_id)

# query-2:
category = session.query(Category).get(category_id)
q = Gift.query.join(SubCategory).filter(SubCategory.category == category)

这些将生成最有效的SQL。对于第二种情况,您可以将此加载包装在一个简单的属性中:

class Category(Base):
    __tablename__ = 'category'

    @property
    def gifts(self):
        q = Gift.query.join(SubCategory).filter(SubCategory.category == self)
        return q.all()

并使用它:

Category.query.get('1234').gifts

选项-2:关系

如果你真的想要一个关系,下面的代码应该这样做:

class Gift(Base):
    # ...
    category = relationship(
        Category,
        uselist=False,
        secondary=SubCategory.__table__,
        primaryjoin=sub_category_id == SubCategory.id,
        secondaryjoin=SubCategory.category_id == Category.id,
        viewonly=True,
        backref="gifts",
    )

和用法:

# one side
gifts = Gift.query.filter(Gift.category == category).all()
# other side
gifts = Category.query.get(category_id).gifts