根据文件:
filter(**kwargs) 返回一个新的 QuerySet,其中包含与给定查找参数匹配的对象。
查找参数 (**kwargs) 应采用下面字段查找中描述的格式。多个参数通过底层 SQL 语句中的 AND 连接。
对我来说,这表明它将返回原始集合中的项目子集。但是我似乎遗漏了一些东西,因为下面的例子并不像我预期的那样:
>>> 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意味着你在 Python 中使用filter()内置函数实现的功能。即:获取满足要求的元素(或者换句话说,丢弃不满足要求的元素)。而且这个定义似乎不允许引入/复制对象。
我知道可以将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}
所以首先问题是方法名称不合适(类似match()会好得多)。第二件事是,我认为创建比 Django 允许的更有效的查询是可能的。我可能错了,如果我有一点时间,我可能会尝试检查这是否属实。