关于python:如何在Django查询集过滤中做不相等的操作?

How do I do a not equal in Django queryset filtering?

在django模型查询集中,我看到比较值有__gt__lt,但是有__ne!=<>吗(不等于?)

我想用一个不等于:

例子:

1
2
3
Model:
    bool a;
    int x;

我想要

1
results = Model.objects.exclude(a=true, x!=5)

!=语法不正确。我试过__ne<>

我最终使用了:

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"两种可用方法,因此您可以随时切换逻辑轮以获得所需的结果。


查询中的field=value语法是field__exact=value的简写。也就是说,Django将查询运算符放在标识符中的查询字段上。Django支持以下运算符:

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建议的filter()exclude(),您就可以得到任何可能的查询所需要的东西。


使用django 1.7很容易创建自定义查找。Django官方文档中有一个__ne查找示例。

您需要首先创建查找本身:

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)

现在,您可以在如下查询中使用__ne查找:

1
results = Model.objects.exclude(a=True, x__ne=5)


在Django 1.9/1.10中有三个选项。

  • excludefilter

    1
    results = Model.objects.exclude(a=true).filter(x=5)
  • 使用Q()对象和~操作符

    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增加了register_lookup装饰像往常一样启用自定义查找:

    1
    results = Model.objects.exclude(a=True, x__ne=5)

  • 在使用模型时,可以使用=__gt__gte__lt__lte,不能使用ne!=<>。但是,您可以在使用q对象时实现更好的过滤。

    您可以避免链接QuerySet.filter()QuerySet.exlude(),并使用:

    1
    2
    from django.db.models import Q
    object_list = QuerySet.filter(~Q(field='not wanted'), field='wanted')


    待定设计决策。同时,使用exclude()

    Django问题追踪系统有一个显著的条目5763,标题为"queryset没有"not equal"筛选器运算符"。这是值得注意的,因为(截至2016年4月)"9年前开业"(在姜戈石器时代)"4年前关闭",以及"最近5个月前改变了"。

    看完讨论,很有趣。基本上,有些人认为应该增加1(14)而另一些人则认为exclude()更清晰,因此__ne更清晰。不应添加。

    (我同意前者,因为后者的论点是大致相当于说python不应该有!=,因为它已经有了==not…)


    你应该这样使用filterexclude

    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。它不检查是否相等。因此,实际上没有任何方法可以使用!=查询调用中的符号。


    你要找的是所有有a=falsex=5的物体。在Django中,|充当查询集之间的OR运算符:

    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))