【问题标题】:Django Queryset Filter on an empty list空列表上的 Django Queryset 过滤器
【发布时间】:2011-08-11 06:02:25
【问题描述】:

我正在构建通过 GET 传递给查询集过滤器的动态过滤器:

for k, v in request.GET.iteritems():
    kwargs[str(k)] = str(v)
students = models.Student.objects.filter( **kwargs )

它适用于我提出的几乎所有查询。但是,我有一个具有多对多关系的相关模型,组。所以一个学生可以是许多组的成员。我可以使用以下方法过滤属于给定组的学生: 'groups__in='+str(group.id)

例如- //example.com/students/?groups__in=1

但我不知道如何过滤不属于任何组的学生。我尝试了以下方法但没有成功:

groups__in=None # students == []
groups__exact=None # students == []
groups__iexact=None # FAIL not that I really expected this to work
groups__isnull=True # students == []

最后一个版本是我希望实际工作的版本。我确信我可以通过将顶部代码修改为类似的东西来实现这一点

if request.GET['something']:
    students = models.Student.objects.exclude(groups__isnull=False)
else:
    students = models.Student.objects.filter( **kwargs )

所以我想问题变成了,我该如何创建

students = models.Student.objects.exclude(groups__isnull=False)

使用 .filter()?

【问题讨论】:

  • 我接受了第一个响应,因为它是正确的,但这并没有解决我的错误。 **kwargs 中有一个扩展问题,我对此提出了一个新问题here。谢谢
  • 感谢@jammon 和@DTing。真正的问题是试图在 GET 中传递一个布尔值。它通过 **kwargs 作为字符串 'True' 传递,而不是 True。传递给models.Student.objects.exclude( **kwargs ) 时有效,因为“真”的计算结果为True。但是共轭不起作用,因为当传递给models.Students.objects.filter( **kwargs ) 时,'False' 仍然评估为True。因此我很困惑。

标签: django filter many-to-many


【解决方案1】:

也许我不明白这个问题。但我明白了:

list(MyMod.objects.exclude(foo__isnull=False)
) == list(MyMod.objects.filter(foo__isnull=True))

【讨论】:

  • 没有 cmets,投反对票和接受的答案...我可以为此或某事获得徽章吗?
【解决方案2】:

我认为models.Student.objects.filter(groups__isnull=True) 应该做你想做的事。正如skyl 指出的,这与models.Student.objects.exclude(groups__isnull=False) 相同。

这个解决方案有什么问题?它可能在您的数据中吗?作为健全性检查,您可以尝试

from django.db.models import Count
models.Student.objects.annotate(gcount=Count('groups').filter(gcount__gt=0)

应该会产生相同的结果。

还有:
如果您从客户端获取不可信的数据并将它们未经检查地提供给您的查询,您应该仔细检查您没有以这种方式打开安全漏洞(或者安全不是您的数据的问题)。

【讨论】:

  • 注释中缺少括号,但编辑应超过 6 个字符
【解决方案3】:
students = models.Student.objects.filter(groups=None)

这是我周围的一些代码的示例:

# add collaborator with no organizations
>>> john = Collaborator(first_name='John', last_name='Doe')                        
>>> john.save()
>>> john.organizations.all()
[]

# add another collaborator with no organizations
>>> jane = Collaborator(first_name='Jane', last_name='Doe')
>>> jane.save()
>>> jane.organizations.all()
[]

# filter for collaborators with no collaborators
>>> collabs_with_no_orgs = Collaborator.objects.filter(organizations=None)
>>> collabs_with_no_orgs
[<Collaborator: John Doe>, <Collaborator: Jane Doe>]

# add organization to collaborator
>>> jane.organizations = [Organization.objects.all()[0]]
>>> jane.save()
>>> jane.organizations.all()
[<Organization: organization 1>]

# filter for collaborators with no organizations
>>> collabs_with_no_orgs = Collaborator.objects.filter(organizations=None)
>>> collabs_with_no_orgs
[<Collaborator: John Doe>]

【讨论】:

    猜你喜欢
    • 2013-12-12
    • 2018-01-21
    • 2016-03-22
    • 2014-07-13
    • 2018-02-15
    • 2013-09-08
    • 2018-06-24
    • 2018-10-09
    • 2020-01-01
    相关资源
    最近更新 更多