How do I do a not equal in Django queryset filtering?
在django模型查询集中,我看到比较值有
我想用一个不等于:
例子:
1 2 3 | Model: bool a; int x; |
我想要
1 | results = Model.objects.exclude(a=true, x!=5) |
我最终使用了:
1 | results = Model.objects.exclude(a=true, x__lt=5).exclude(a=true, x__gt=5) |
也许Q对象可以帮助解决这个问题。我从来没有使用过它们,但它们似乎可以被否定并组合起来,就像普通的Python表达式一样。
最新消息:我刚试过,看起来效果不错:
1 2 3 4 5 6 | >>> from myapp.models import Entry >>> from django.db.models import Q >>> Entry.objects.filter(~Q(id = 3)) [<Entry: Entry object>, <Entry: Entry object>, <Entry: Entry object>, ...] |
您的查询似乎有一个双负数,您希望排除X不是5的所有行,所以换句话说,您希望包括X是5的所有行。我相信这会成功的。
1 | results = Model.objects.filter(x=5).exclude(a=true) |
要回答您的特定问题,没有"不等于"的方法,但这可能是因为Django有"filter"和"exclude"两种可用方法,因此您可以随时切换逻辑轮以获得所需的结果。
查询中的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | exact iexact contains icontains in gt gte lt lte startswith istartswith endswith iendswith range year month day week_day isnull search regex iregex |
我敢肯定,将它们与Dave Vogt建议的Q对象结合起来,并使用Jason Baker建议的
使用django 1.7很容易创建自定义查找。Django官方文档中有一个
您需要首先创建查找本身:
1 2 3 4 5 6 7 8 9 10 | from django.db.models import Lookup class NotEqual(Lookup): lookup_name = 'ne' def as_sql(self, qn, connection): lhs, lhs_params = self.process_lhs(qn, connection) rhs, rhs_params = self.process_rhs(qn, connection) params = lhs_params + rhs_params return '%s <> %s' % (lhs, rhs), params |
然后您需要注册它:
1 2 | from django.db.models.fields import Field Field.register_lookup(NotEqual) |
现在,您可以在如下查询中使用
1 | results = Model.objects.exclude(a=True, x__ne=5) |
在Django 1.9/1.10中有三个选项。
链
1 | results = Model.objects.exclude(a=true).filter(x=5) |
使用
1 2 | from django.db.models import Q object_list = QuerySet.filter(~Q(a=True), x=5) |
注册自定义查找函数
1 2 3 4 5 6 7 8 9 10 11 12 | from django.db.models import Lookup from django.db.models.fields import Field @Field.register_lookup class NotEqual(Lookup): lookup_name = 'ne' def as_sql(self, compiler, connection): lhs, lhs_params = self.process_lhs(compiler, connection) rhs, rhs_params = self.process_rhs(compiler, connection) params = lhs_params + rhs_params return '%s <> %s' % (lhs, rhs), params |
django 1.8增加了
1 | results = Model.objects.exclude(a=True, x__ne=5) |
在使用模型时,可以使用
您可以避免链接
1 2 | from django.db.models import Q object_list = QuerySet.filter(~Q(field='not wanted'), field='wanted') |
待定设计决策。同时,使用
Django问题追踪系统有一个显著的条目5763,标题为"queryset没有"not equal"筛选器运算符"。这是值得注意的,因为(截至2016年4月)"9年前开业"(在姜戈石器时代)"4年前关闭",以及"最近5个月前改变了"。
看完讨论,很有趣。基本上,有些人认为应该增加1(14)而另一些人则认为
(我同意前者,因为后者的论点是大致相当于说python不应该有
你应该这样使用
1 | results = Model.objects.exclude(a=true).filter(x=5) |
使用排除和筛选
1 | results = Model.objects.filter(x=5).exclude(a=true) |
最后一位代码将排除X处的所有对象!=5,a为真。试试这个:
1 | results = Model.objects.filter(a=False, x=5) |
记住,上面一行中的=符号为参数a赋值为假,为参数x赋值为数字5。它不检查是否相等。因此,实际上没有任何方法可以使用!=查询调用中的符号。
你要找的是所有有
1 | results = Model.objects.filter(a=false)|Model.objects.filter(x=5) |
django model values(disclosure:author)提供了notequal查找的实现,如此答案所示。它还为它提供语法支持:
1 2 | from model_values import F Model.objects.exclude(F.x != 5, a=True) |
1 | results = Model.objects.filter(a = True).exclude(x = 5) |
生成此SQL:
1 | select * from tablex where a != 0 and x !=5 |
SQL取决于表示真/假字段的方式和数据库引擎。不过,Django代码是您所需要的。
当心这个问题的许多错误答案!
杰拉德的逻辑是正确的,尽管它将返回一个列表而不是一个查询集(这可能不重要)。
如果需要查询集,请使用q:
1 2 | from django.db.models import Q results = Model.objects.filter(Q(a=false) | Q(x=5)) |