标签归档:django-queryset

如何在Django queryset过滤中执行不等于?

问题:如何在Django queryset过滤中执行不等于?

在Django模型QuerySets中,我看到比较值存在__gt__lt,但是存在__ne// !=/ <>不等于?)。

我想使用不等于过滤掉:

例:

Model:
    bool a;
    int x;

我想要

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

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

我最终使用:

results = Model.objects.exclude(a=true, x__lt=5).exclude(a=true, x__gt=5)

In Django model QuerySets, I see that there is a __gt and __lt for comparitive values, but is there a __ne/!=/<> (not equals?)

I want to filter out using a not equals:

Example:

Model:
    bool a;
    int x;

I want

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

The != is not correct syntax. I tried __ne, <>.

I ended up using:

results = Model.objects.exclude(a=true, x__lt=5).exclude(a=true, x__gt=5)

回答 0

也许Q对象可以解决这个问题。我从未使用过它们,但似乎可以将它们取反并组合起来,就像普通的python表达式一样。

更新:我只是尝试了一下,它似乎工作得很好:

>>> 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>, ...]

Maybe Q objects could be of help for this problem. I’ve never used them but it seems they can be negated and combined much like normal python expressions.

Update: I Just tried it out, it seems to work pretty well:

>>> 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>, ...]

回答 1

您的查询似乎有一个双重否定,您想排除x不为5的所有行,换句话说,您想包括x为5的所有行。我相信这可以解决问题。

results = Model.objects.filter(x=5).exclude(a=true)

要回答您的特定问题,不存在“不等于”的问题,但这可能是因为django同时提供了“过滤器”和“排除”方法,因此您始终可以切换逻辑回合以获得所需的结果。

Your query appears to have a double negative, you want to exclude all rows where x is not 5, so in other words you want to include all rows where x IS 5. I believe this will do the trick.

results = Model.objects.filter(x=5).exclude(a=true)

To answer your specific question, there is no “not equal to” but that’s probably because django has both “filter” and “exclude” methods available so you can always just switch the logic round to get the desired result.


回答 2

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

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对象结合使用,filter()或者exclude()Jason Baker所建议的那样使用,您将获得几乎所有可能查询所需的确切信息。

the field=value syntax in queries is a shorthand for field__exact=value. That is to say that Django puts query operators on query fields in the identifiers. Django supports the following operators:

exact
iexact
contains
icontains
in
gt
gte
lt
lte
startswith
istartswith
endswith
iendswith
range
year
month
day
week_day
isnull
search
regex
iregex

I’m sure by combining these with the Q objects as Dave Vogt suggests and using filter() or exclude() as Jason Baker suggests you’ll get exactly what you need for just about any possible query.


回答 3

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

您需要先创建查找本身:

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

然后,您需要注册:

from django.db.models.fields import Field
Field.register_lookup(NotEqual)

现在,您可以__ne像下面这样在查询中使用查找:

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

It’s easy to create a custom lookup with Django 1.7. There’s an __ne lookup example in Django official documentation.

You need to create the lookup itself first:

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

Then you need to register it:

from django.db.models.fields import Field
Field.register_lookup(NotEqual)

And now you can use the __ne lookup in your queries like this:

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

回答 4

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

  1. excludefilter

    results = Model.objects.exclude(a=true).filter(x=5)
  2. 使用Q()对象~运算符

    from django.db.models import Q
    object_list = QuerySet.filter(~Q(a=True), x=5)
  3. 注册自定义查找功能

    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

    register_lookup在加装饰的Django 1.8和启用自定义查找和往常一样:

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

In Django 1.9/1.10 there are three options.

  1. Chain exclude and filter

    results = Model.objects.exclude(a=true).filter(x=5)
    
  2. Use Q() objects and the ~ operator

    from django.db.models import Q
    object_list = QuerySet.filter(~Q(a=True), x=5)
    
  3. Register a custom lookup function

    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
    

    The register_lookup decorator was added in Django 1.8 and enables custom lookup as usual:

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

回答 5

虽然与模型,您可以用过滤=__gt__gte__lt__lte,你不能使用ne!=或者<>。但是,使用Q对象可以实现更好的过滤。

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

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

While with the Models, you can filter with =, __gt, __gte, __lt, __lte, you cannot use ne, != or <>. However, you can achieve better filtering on using the Q object.

You can avoid chaining QuerySet.filter() and QuerySet.exlude(), and use this:

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

回答 6

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

Django问题追踪器具有引人注目的条目#5763,标题为“ Queryset没有“不相等”的过滤运算符”。值得注意的是,(截至2016年4月)它是​​“在9年前开放”(在Django石器时代),“在4年前关闭”和“在5个月前最后一次更改”。

通读讨论,这很有趣。基本上,一些人认为__ne应增加也有人说exclude()是清晰的,因此__ne 应该添加。

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

Pending design decision. Meanwhile, use exclude()

The Django issue tracker has the remarkable entry #5763, titled “Queryset doesn’t have a “not equal” filter operator”. It is remarkable because (as of April 2016) it was “opened 9 years ago” (in the Django stone age), “closed 4 years ago”, and “last changed 5 months ago”.

Read through the discussion, it is interesting. Basically, some people argue __ne should be added while others say exclude() is clearer and hence __ne should not be added.

(I agree with the former, because the latter argument is roughly equivalent to saying Python should not have != because it has == and not already…)


回答 7

使用排除和过滤

results = Model.objects.filter(x=5).exclude(a=true)

Using exclude and filter

results = Model.objects.filter(x=5).exclude(a=true)

回答 8

您应该使用filterexclude喜欢这个

results = Model.objects.exclude(a=true).filter(x=5)

You should use filter and exclude like this

results = Model.objects.exclude(a=true).filter(x=5)

回答 9

代码的最后一位将排除x!= 5并且a为True的所有对象。尝试这个:

results = Model.objects.filter(a=False, x=5)

请记住,上一行中的=符号将False赋给参数a,并将数字5赋给参数x。它不是在检查是否相等。因此,实际上没有任何方法可以在查询调用中使用!=符号。

The last bit of code will exclude all objects where x!=5 and a is True. Try this:

results = Model.objects.filter(a=False, x=5)

Remember, the = sign in the above line is assigning False to the parameter a and the number 5 to the parameter x. It’s not checking for equality. Thus, there isn’t really any way to use the != symbol in a query call.


回答 10

结果= Model.objects.filter(a = True).exclude(x = 5)
生成此sql:
从tablex中选择*,其中a = 0且x!= 5
sql取决于您的True / False字段的表示方式以及数据库引擎。Django代码是您所需要的。

results = Model.objects.filter(a = True).exclude(x = 5)
Generetes this sql:
select * from tablex where a != 0 and x !=5
The sql depends on how your True/False field is represented, and the database engine. The django code is all you need though.

回答 11

Django-model-values(公开:作者)提供了NotEqual查找的实现,如此答案所示。它还为此提供了语法支持:

from model_values import F
Model.objects.exclude(F.x != 5, a=True)

Django-model-values (disclosure: author) provides an implementation of the NotEqual lookup, as in this answer. It also provides syntactic support for it:

from model_values import F
Model.objects.exclude(F.x != 5, a=True)

回答 12

您要查找的所有具有a=false 或的 对象x=5。在Django中,|充当查询集OR之间的运算符:

results = Model.objects.filter(a=false)|Model.objects.filter(x=5)

What you are looking for are all objects that have either a=false or x=5. In Django, | serves as OR operator between querysets:

results = Model.objects.filter(a=false)|Model.objects.filter(x=5)

回答 13

这将给您想要的结果。

from django.db.models import Q
results = Model.objects.exclude(Q(a=True) & ~Q(x=5))

对于不相等,可以~在相等查询上使用。显然,Q可以用来达到相等的查询。

This will give your desired result.

from django.db.models import Q
results = Model.objects.exclude(Q(a=True) & ~Q(x=5))

for not equal you can use ~ on an equal query. obviously, Q can be used to reach the equal query.


回答 14

注意此问题的许多错误答案!

Gerard的逻辑是正确的,尽管它将返回一个列表而不是一个查询集(这可能无关紧要)。

如果需要查询集,请使用Q:

from django.db.models import Q
results = Model.objects.filter(Q(a=false) | Q(x=5))

Watch out for lots of incorrect answers to this question!

Gerard’s logic is correct, though it will return a list rather than a queryset (which might not matter).

If you need a queryset, use Q:

from django.db.models import Q
results = Model.objects.filter(Q(a=false) | Q(x=5))