根据documentation:



我认为这将返回原始集中的项的子集。
但是我似乎丢失了一些东西,因为以下示例的行为不符合我的预期:

>>> 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)'

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

关于它为什么这样表现的解释也很不错,对于我来说filter意味着您使用python内置函数 filter()实现的功能。即:采用满足要求的元素(或换句话说,丢弃不满足要求的元素)。而且此定义似乎不允许引入/复制对象。

我知道可以将distant()应用于整个过程,但这仍然会导致相当丑陋的查询(并且可能比可能慢的查询):
>>> 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允许我做的效率更高的查询。在这方面我可能是错的,如果我有一点时间,我可能会尝试检查是否正确。

最佳答案

这有点丑陋,但是可以(没有任何类型安全性):

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

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

PS!我在Django 1.6b2上测试了您的查询,并得到了相同的不必要的复杂查询。

10-05 20:49
查看更多