【发布时间】:2013-08-29 04:46:35
【问题描述】:
filter(**kwargs) 返回一个包含匹配对象的新 QuerySet 给定的查找参数。
查找参数 (**kwargs) 应采用中所述的格式 下面的字段查找。多个参数通过 AND 连接 底层 SQL 语句。
对我来说,这表明它将返回原始集合中的项目子集。 但是我似乎遗漏了一些东西,因为下面的例子并不像我预期的那样:
>>> 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}
所以首先问题是方法名称不合适(类似 match() 会好得多)。 第二件事是,我认为创建比 Django 允许的更有效的查询是可能的。我可能错了,如果我有一点时间,我可能会尝试检查是否属实。
【问题讨论】:
-
所以你想要独特的儿童领域?
-
给定玩具子集,我想获得拥有这些玩具的孩子子集。实际上我的情况稍微复杂一些,因为实际上我有“所有者”和“last_played_with”字段。我想要的是拥有或玩过这些玩具的所有孩子的清单。如果可能的话,我想了解为什么 filter() 会重复对象。
-
你能提供完整的模型吗?机智 last_played 和其他相关领域。
-
使用
distinct()不是一个坏习惯,也不会减慢速度。这实际上是不编写自己的 SQL 的推荐方法。至于filter(),它实际上在文档中By default, a QuerySet will not eliminate duplicate rows。 -
根据我对 filter() 应该如何工作的理解,它不应该引入任何连接(至少在这种情况下),而只是扩展 WHERE 子句的内容。尽管我理解为什么该查询返回它返回的内容,但我不明白为什么我会得到这样的查询。更不用说 Django 应该将我与实际的 SQL 隔离开来,所以我想了解该短语的语义。并且没有“__in”并不意味着它会产生重复的项目。