【发布时间】:2021-12-27 03:10:43
【问题描述】:
鉴于这些模型:
from django.db import models
class Foo(models.Model):
pass # table with only one column, i.e. a primary key 'id' of type integer
class Bar(models.Model):
value = models.TextField()
foo = models.ForeignKey(Foo, on_delete=models.CASCADE, related_name='bars')
如何创建一个过滤器,返回与至少一个 Bar 相关的所有Foos 以及非零 value?
我知道可以首先选择非零的Bars,然后返回与它们相关的Foos。但我特意在寻找一种直接在 QuerySet 中获取相关Foos 的解决方案。原因是它可以很容易地应用于嵌套更深层次的关系。
什么不起作用
创建一个查询集很简单,它返回与至少一个Bar 相关的所有Foos,零 value:
Foo.objects.filter(bars__value="zero")
但是,由于 Django 的过滤器方法中缺少“不等于”运算符,所以不可能做这样的事情:
Foo.objects.filter(bars__value__not_equal="zero") # Unsupported lookup 'not_equal' for TextField
使用exclude:
Foo.objects.exclude(bars__value="zero")
不会产生所需的输出,因为它排除了所有与至少一个具有零值的Bar 相关的Foos。
所以,如果一个Foo 与两个Bars 相关,其中一个value 为0,另一个value 为非零值,则会被此exclude 过滤掉.然而,我们的意图是包含它,因为它与至少一个具有非零值的Bar 相关。
同样,使用取反的Q 对象:
Foo.objects.filter(~models.Q(bars__value="zero"))
也不会产生所需的输出,因为它只会包括所有Foos,这些Foos 不与任何 Bars 相关且值为零。
它将创建与上述exclude 方法相同的查询集。
注意事项
B.value 字段的类型已被有意选择为示例中的文本,以强调我正在寻找一个通用解决方案,其中无法通过使用例如模拟“不等于”运算符。 “小于”和“大于”运算符的组合。
【问题讨论】:
标签: python django django-queryset