【问题标题】:Django: filter queryset by intersection resultDjango:按交集结果过滤查询集
【发布时间】:2013-04-20 19:57:52
【问题描述】:

假设我有一个与 Feature 存在 M2M 关系的 Item 模型:

class Item(models.Model):
    features = models.ManyToManyField(to = 'Feature')

现在我想过滤 Item 查询集以仅包含至少具有所有指定功能的项目。

假设可能的功能是:CameraTouchscreenKeyboard

现在我想选择 所有具有 相机和键盘的项目

有什么解决办法吗?

【问题讨论】:

    标签: python sql django postgresql orm


    【解决方案1】:

    假设功能的模型有一个名为“名称”的字段,您可以在值列表中过滤与该字段匹配的项目。这样的事情会起作用:

    Item.objects.filter(features__name__in=['Camera', 'Touchscreen', 'Keyboard'])
    

    更新:

    正如stalk 所说的here,要获得与您需要对查询执行许多“过滤器”的所有功能匹配的项目。动态获取它的一种方法是:

    features = ['Camera', 'Touchscreen', 'Keyboard']
    items = Item.objects.all()
    
    for feature in features:
      items = items.filter(feature__name=feature)
    

    这样你可以传递一个动态的特征列表来匹配项目。

    【讨论】:

    • 此查询将返回提供的列表中具有至少一个特征的所有项目。问题是“我想选择所有具有 相机和键盘的项目”。所以,查询必须是Item.objects.filter(features__name='Camera').filter(features__name='Keyboard')
    • 好吧,多重过滤是一种选择,但它有点棘手,并且 - 当再次过滤许多特征时,会导致查询字符串显着增长。我正在考虑在 python 端过滤它..
    • 如果你使用python进行过滤,你需要从数据库中获取每个相关的对象,这会增加查询的数量。相反,使用过滤器(任意次数)将只创建一个对数据库的查询,因为 QuerySet 是惰性的,您可以在此处阅读:docs.djangoproject.com/en/dev/topics/db/queries/…
    • 对于每个要过滤的“特征”,还有一个 JOIN。当有 50 个功能时,我害怕 sql 性能 ;)
    【解决方案2】:

    如果您的特征模型使用名称字段,那么这应该可以:

    Items.objects.filter(features__name='Camera', features__name='Keyboard')

    编辑: 上述查询中的语法错误。应该是 2 个过滤器链接在一起:

    Items.objects.filter(features__name='Camera').filter(features_name='Keyboard')

    【讨论】:

    • 这又是 Python 语法,你在重复关键字参数。但是双重过滤(Item.objects.filter(..).filter(..))按预期工作。然而,这有点棘手,正在寻找一种更清洁的方式;)
    猜你喜欢
    • 2012-05-15
    • 2016-08-13
    • 2018-09-26
    • 1970-01-01
    • 2020-08-22
    • 2019-04-15
    • 2011-09-29
    相关资源
    最近更新 更多