简体   繁体   English

动态(自引用)关系应用过滤器

[英]Dynamically applied filter on (self-referential) relationship

I have a model that I would like to query with a filter. 我有一个要使用过滤器查询的模型。 I also want this filter to be applied on its children (one-to-many self-referential relationship). 我还希望将此过滤器应用于其子级(一对多的自我参照关系)。 Example: 例:

class Item(Model):
    __tablename__ = 'item'

    id = Column(Integer, primary_key=True)
    color = Column(String)

    parent_id = Column(Integer, ForeignKey('item.id'))
    children = relationship(
        'Item',
        backref=backref('parent', remote_side=[id]),
        lazy='dynamic'
    )

    item = session.query(Item).filter(Item.color == 'blue').one()

Now I want to apply the same filter on the children collection once, and be able to access the filtered collection in a transparent way later. 现在,我想一次children集合应用相同的过滤器,并在以后能够以透明方式访问过滤后的集合。

I could imagine something like: 可以想象像这样的东西:

item.children.apply_filter(Item.color == 'blue')  # `children` is dynamic

and then accessing item.children would be equivalent to accessing item.children.filter(Item.color == 'blue').all() now. 然后访问item.children等同于立即访问item.children.filter(Item.color == 'blue').all() Note that with this solution, the fact that the relationship is self-referential doesn't matter. 请注意,使用此解决方案,关系是自引用的事实无关紧要。

SQLAlchemy's API is huge and I can't figure out if there is a proper way to do this (or something equivalent). SQLAlchemy的API很大,我不知道是否有适当的方法来执行此操作(或等效方法)。

(Is it possible to modify the primaryjoin of a relationship at query time ? Or give it a parameter ?) (是否可以在查询时修改关系的主primaryjoin ?或者给它一个参数?)

Please note that if you have multiple items with the same color, your original query item = session.query(Item).filter(Item.color == 'blue').one() will fail. 请注意,如果您有多个具有相同颜色的项目,则原始查询item = session.query(Item).filter(Item.color == 'blue').one()将失败。

When you get past that and get your (parent) Item instance: 当您通过该操作并获得(父) Item实例时:

my_item = session.query(Item).filter(Item.color == 'blue')[0]
# my_item = session.query(Item).filter(Item.color == 'blue').filter(Item.parent == None).one() # assume this is only one root item per color

because children is dynamic , my_item.children will return you a query. 由于childrendynamic ,因此my_item.children将向您返回查询。 In this case you simply apply another filter and you are done: 在这种情况下,您只需应用另一个过滤器即可完成:

my_blue_children = my_item.children.filter(Item.color == 'blue').all()

The filter clause will now apply a filter to the select statement loading children. 现在, filter子句将对选择语句加载子级应用过滤器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM