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 中搜索 ,则必须使用 containsicontains。只需使用 Q(author__name__icontains=n) 更新 Q 对象。

【讨论】:

如果xxx是包含字符串的变量名,则不需要'' 是的,你是对的。在问题的最后一次更新之前不清楚 XXX 是什么,所以我试图通过说它必须是一个字符串来说明它。

以上是关于Django 不在相关领域的主要内容,如果未能解决你的问题,请参考以下文章

蛞蝓 Django 领域;我们需要这个吗? [复制]

Python五大应用领域是啥

使用swift存储数据而不在领域中制作模型

Django 模型创建共同独特的领域

makemigrations 忽略所有领域 (DJANGO)

markdown Django时区模型领域