Django 不在相关领域
Posted
技术标签:
【中文标题】Django 不在相关领域【英文标题】:Django Not in for Related Fields 【发布时间】:2015-08-12 20:42:05 【问题描述】:当我有相关字段时,我将如何在 Django 中进行not in
过滤器?
class Publisher(Model):
pass
class Author(Model):
name = models.CharField(...)
publisher = models.ForeignKey(Publisher)
我会写:
Publisher.objects.filter(author__name__in=XXX)
这不起作用:
Publisher.objects.filter(author__name__not_in=XXX)
虽然Django equivalent of SQL not in 声称您可以使用exclude
,但这是不正确的:
Publisher.objects.exclude(author__name__in=XXX)
XXX
是一个名称列表。
澄清我想得到什么:我想找到所有作者不在该列表中的出版商。注意:这些出版商可能在该列表中也有作者。
假设我有两个出版商 A、B 和以下出版商的作者:
A: Alex, Bob, Greg
B: Alex, Greg
xxx 是 ['Alex', 'Greg']
我想查找作者不在该列表中的任何出版商。在这种情况下,应该返回 A,因为 A 的作者 Bob 不在该列表中。
【问题讨论】:
【参考方案1】:检查exclude()
函数。它是 filter()
函数的逆函数,但完全符合您的要求。
注意你也可以chain functions together:
>>> Entry.objects.filter(
... headline__startswith='What'
... ).exclude(
... pub_date__gte=datetime.date.today()
... ).filter(
... pub_date__gte=datetime(2005, 1, 30)
... )
【讨论】:
我很确定在这种情况下我不想要过滤器的倒数。我想找到所有作者不在该列表中的出版商。注意:这些出版商可能在该列表中也有作者。【参考方案2】:什么是XXX
,如果是list
,您应该可以在查询中使用exclude
。
Publisher.objects.exclude(author__name__in=XXX) # Remember XXX must be a list
如果是string
,你应该使用:
Publisher.objects.exclude(author__name__contains=XXX)
或者如果大小写无关紧要:
Publisher.objects.exclude(author__name__icontains=XXX)
【讨论】:
更新显示XXX
是一个列表。每***.com/questions/30538768/… exclude 不是我想要的。
请明确exclude
不起作用,或者它没有返回您期望的结果?
它没有返回我想要的。我不想否定整个过滤器,我想否定 in。
你能举个例子,包括数据、XXX 值和你的期望吗?
更新了更丰富的例子。【参考方案3】:
可以使用以下内容:
Publisher.author.filter(author__in=Author.objects.exclude(name__in=xxx))
潜在的巨大子查询会带来性能成本,尤其是在不能很好地处理子查询的 mysql 上。
另一种方法是实现 NOT IN
custom lookup,这从 1.7 开始就可以实现。它看起来像这样:
class NotInLookup(Lookup):
lookup_name = 'not_in'
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 NOT IN (%s)' % (lhs, rhs), params
您必须调查文档以及可能的 source code of IN
,才能找到编写此查找的正确方法。可能有兴趣将它添加到核心中,所以如果你让它工作,请随时将它放在邮件列表中https://groups.google.com/forum/#!forum/django-developers。
【讨论】:
【参考方案4】:看起来Q objects 很适合这个查询。
您可以先建立查询参数。
import operator
query = reduce(
lambda x, y: operator.or_(Q(author__name=x), Q(author__name=y)),
XXX
)
# query would be something like Q(author__name='Alex') | Q(author__name='Greg')
Publisher.objects.exclude(query)
使用完全匹配的示例,如果您要在 CharField 中搜索 ,则必须使用 contains
或 icontains
。只需使用 Q(author__name__icontains=n)
更新 Q 对象。
【讨论】:
如果xxx是包含字符串的变量名,则不需要''
。
是的,你是对的。在问题的最后一次更新之前不清楚 XXX 是什么,所以我试图通过说它必须是一个字符串来说明它。以上是关于Django 不在相关领域的主要内容,如果未能解决你的问题,请参考以下文章