gpt4 book ai didi

python - Django - 如何使用 QuerySet 进行过滤以获取对象的子集?

转载 作者:太空狗 更新时间:2023-10-30 00:36:24 24 4
gpt4 key购买 nike

根据 documentation :

filter(**kwargs) Returns a new QuerySet containing objects that match the given lookup parameters.

The lookup parameters (**kwargs) should be in the format described in Field lookups below. Multiple parameters are joined via AND in the underlying SQL statement.

这对我来说表明它将返回原始集合中项目的子集。但是我似乎遗漏了一些东西,因为下面的例子并不像我预期的那样:

>>> kids = Kid.objects.all()
>>> tuple(k.name for k in kids)
(u'Bob',)
>>> toys = Toy.objects.all()
>>> tuple( (t.name, t.owner.name) for t in toys)
((u'car', u'Bob'), (u'bear', u'Bob'))
>>> subsel = Kid.objects.filter( owns__in = toys )
>>> tuple( k.name for k in subsel )
(u'Bob', u'Bob')
>>> str(subsel.query)
'SELECT "bug_kid"."id", "bug_kid"."name" FROM "bug_kid" INNER JOIN "bug_toy" ON ("bug_kid"."id" = "bug_toy"."owner_id") WHERE "bug_toy"."id" IN (SELECT U0."id" FROM "bug_toy" U0)'

正如您在上面看到的 subsel 最终返回重复记录,这不是我想要的。我的问题是获取子集的正确方法是什么? (注意:根据定义设置不会有同一个对象的多次出现)

关于为什么它的行为的解释也很好,因为对我来说filter意味着你用filter()构建的Python 中的 -in 函数。即:采用满足要求的元素(或者换句话说,丢弃不满足要求的元素)。而且这个定义似乎不允许引入/复制对象。

我知道可以对整个事情应用 distinct(),但这仍然会导致相当丑陋(并且可能比可能的更慢)的查询:

>>> str( subsel.distinct().query )
'SELECT DISTINCT "bug_kid"."id", "bug_kid"."name" FROM "bug_kid" INNER JOIN "bug_toy" ON ("bug_kid"."id" = "bug_toy"."owner_id") WHERE "bug_toy"."id" IN (SELECT U0."id" FROM "bug_toy" U0)'

为了完整性,我的 models.py:

from django.db import models

class Kid(models.Model):
name = models.CharField(max_length=200)

class Toy(models.Model):
name = models.CharField(max_length=200)
owner = models.ForeignKey(Kid, related_name='owns')

编辑:

与@limelight 交谈后得出的结论是,我的 问题是我希望filter() 的行为符合字典定义。即它如何在 Python 或任何其他健全的框架/语言中工作。

更准确地说,如果我设置了 A = {x,y,z}然后我调用 A.filter( <predicate> )我不希望任何元素被复制。然而,使用 Django 的 QuerySet 时,它的行为如下:

A = {x,y,z}
A.filter( <predicate> )
# now A i.e. = {x,x}

所以首先问题是方法名称不合适(类似ma​​tch() 会好得多)。第二件事是我认为可以创建比 Django 允许的更高效的查询。我在这方面可能是错的,如果我有一点时间,我可能会尝试检查这是否属实。

最佳答案

这有点丑陋,但有效(没有任何类型安全):

toy_owners = Toy.objects.values("owner_id")  # optionally with .distinct()
Kid.objects.filter(id__in=toy_owners)

如果性能不是问题,我认为@limelights 是对的。

附言!我在 Django 1.6b2 上测试了你的查询,得到了同样不必要的复杂查询。

关于python - Django - 如何使用 QuerySet 进行过滤以获取对象的子集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18448468/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com