在 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)
a=true
,然后对其余的应用 x=5
过滤器。预期的查询仅需要具有 a=true
和 x!=5
的查询。不同之处在于所有带有 a=true
和 x=5
的人也被过滤掉了。
为此,您可以使用 Q objects。它们可以用 ~
运算符取反,并像普通的 Python 表达式一样组合:
from myapp.models import Entry
from django.db.models import Q
Entry.objects.filter(~Q(id=3))
将返回除以 3
作为 ID 的条目之外的所有条目:
[<Entry: Entry object>, <Entry: Entry object>, <Entry: Entry object>, ...]
您的查询似乎有双重否定,您想要排除 x
不是 5 的所有行,因此换句话说,您想要包括 x
5 的所有行。我相信这一点会成功的:
results = Model.objects.filter(x=5).exclude(a=True)
要回答您的具体问题,没有“不等于”field lookup,但这可能是因为 Django 同时提供了 filter
和 exclude
方法,因此您始终可以切换逻辑以获得所需的结果。
results = Model.objects.filter(a=true).exclude(x=5)
exclude
和 filter
调用的顺序没有任何意义。 WHERE
子句中条件的顺序发生了变化,但这有什么关系呢?
查询中的 field=value
语法是 field__exact=value
的简写。也就是说Django puts query operators on query fields in the identifiers。 Django 支持以下运算符:
exact
iexact
contains
icontains
in
gt
gte
lt
lte
startswith
istartswith
endswith
iendswith
range
date
year
iso_year
month
day
week
week_day
iso_week_day
quarter
time
hour
minute
second
isnull
regex
iregex
我确信通过将这些与 Q 对象组合为 Dave Vogt suggests 并使用 filter()
或 exclude()
作为 Jason Baker suggests,您将获得几乎任何可能查询所需的内容。
tg=Tag.objects.filter(user=request.user).exclude(name__regex=r'^(public|url)$')
的东西,它可以工作。
icontains
、iexact
和类似中的 i 代表“忽略区分大小写”。它不适用于“逆”。
exclude()
与多个术语一起使用时,您可能希望使用 OR
运算符组成命题,例如 exclude(Q(field1__queryop1=value1) | Q(field2__queryop2=value2))
,以便排除两种条件下的结果。
有三个选项:
链式排除和过滤结果 = Model.objects.exclude(a=True).filter(x=5) 使用 Q() 对象和 ~ 操作符 from django.db.models import Q object_list = QuerySet.filter(~Q(a =True), x=5) 从 django.db.models 注册自定义查找函数 import Lookup from django.db.models import Field @Field.register_lookup class NotEqual(Lookup): lookup_name = 'ne' def as_sql(self, compiler , 连接): 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可以照常使用: results = Model.objects.exclude(a=True, x__ne=5)
exclude
将在 WHERE 子句中添加一些内容,因此它非常有效。请参阅docs.djangoproject.com/en/3.2/ref/models/querysets/#exclude。 @阿努帕姆
创建自定义查找很容易,Django's official documentation 中有一个 __ne
查找示例。
您需要先创建查找本身:
from django.db.models import 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
然后你需要注册它:
from django.db.models import Field
Field.register_lookup(NotEqual)
现在您可以在查询中使用 __ne
查找,如下所示:
results = Model.objects.exclude(a=True, x__ne=5)
虽然您可以使用 =
、__gt
、__gte
、__lt
、__lte
过滤模型,但不能使用 ne
或 !=
。但是,您可以使用 Q 对象实现更好的过滤。
您可以避免链接 QuerySet.filter()
和 QuerySet.exclude()
,并使用此:
from django.db.models import Q
object_list = QuerySet.filter(~Q(field='not wanted'), field='wanted')
待定的设计决定。同时,使用 exclude()
Django 问题跟踪器具有非凡的 entry #5763,标题为“Queryset 没有“不等于”过滤器运算符”。这很了不起,因为(截至 2016 年 4 月)它是“9 年前开放的”(在 Django 石器时代)、“4 年前关闭”和“5 个月前最后一次更改”。
通读讨论,很有趣。基本上,有些人认为应该添加 __ne
,而另一些人则认为 exclude()
更清晰,因此应该不添加 __ne
。
(我同意前者,因为后者的论点大致相当于说 Python 不应该有 !=
,因为它已经有 ==
和 not
...)
使用排除和过滤
results = Model.objects.filter(x=5).exclude(a=true)
您应该像这样使用 filter
和 exclude
results = Model.objects.exclude(a=true).filter(x=5)
Django-model-values(披露:作者)提供了 NotEqual 查找的实现,如 this answer。它还为其提供语法支持:
from model_values import F
Model.objects.exclude(F.x != 5, a=True)
这将给出您想要的结果。
from django.db.models import Q
results = Model.objects.exclude(Q(a=True) & ~Q(x=5))
对于 不等于,您可以在相等查询上使用 ~
。显然,Q
可用于达到相等查询。
Q(a=True) and ~Q(x=5)
中使用“and”将评估为 ~Q(x=5)
作为 .exclude
的参数。请阅读:docs.python.org/3/reference/expressions.html#boolean-operations 和 docs.python.org/3/reference/…。
最后一段代码将排除 x!=5 且 a 为 True 的所有对象。尝试这个:
results = Model.objects.filter(a=False, x=5)
请记住,上一行中的 = 符号将 False 分配给参数 a,将数字 5 分配给参数 x。它不是检查平等。因此,实际上没有任何方法可以在查询调用中使用 != 符号。
results = Model.objects.filter(a__in=[False,None],x=5)
您要查找的是具有 a=false
或 x=5
的所有对象。在 Django 中,|
充当查询集之间的 OR
运算符:
results = Model.objects.filter(a=false)|Model.objects.filter(x=5)
results = Model.objects.filter(a = True).exclude(x = 5)
select * from tablex where a != 0 and x !=5
这应该工作
results = Model.objects.filter(x=5).exclude(a=True)
注意这个问题的许多错误答案!
Gerard 的逻辑是正确的,尽管它会返回一个列表而不是一个查询集(这可能无关紧要)。
如果您需要查询集,请使用 Q:
from django.db.models import Q
results = Model.objects.filter(Q(a=false) | Q(x=5))
如果我们需要根据我们可以使用的子查询集排除/否定,
当条件表达式返回一个布尔值时,可以直接在过滤器中使用它。这里 non_unique_account_type
返回一个布尔值。但是,我们仍然可以在过滤器中使用它。
>>> non_unique_account_type = Client.objects.filter(
... account_type=OuterRef('account_type'),
... ).exclude(pk=OuterRef('pk')).values('pk')
>>> Client.objects.filter(~Exists(non_unique_account_type))
在 SQL 术语中,它的计算结果为:
SELECT * FROM client c0
WHERE NOT EXISTS (
SELECT c1.id
FROM client c1
WHERE c1.account_type = c0.account_type AND NOT c1.id = c0.id
)
不定期副业成功案例分享
Entry.objects.filter(~Q(id=3))
而不是Entry.objects.exclude(id=3)
?~Q
查询与其他查询串在一起。 docs.djangoproject.com/en/3.2/topics/db/queries/…Entry.objects.filter(~Q(param="good")).exists()