我想我错过了一些关于 Django 的 filter() 方法应该如何工作的非常基本和基本的东西。
使用以下模型:
class Collection(models.Model):
pass
class Item(models.Model):
flag = models.BooleanField()
collection = models.ForeignKey(Collection)
通过调用问题底部的 populate() 函数提供的数据,尝试在 ./manage.py shell 中执行以下命令:
len(Collection.objects.filter(item__flag=True))
我的期望是这将打印“2”,这是至少有一个带有 flag=True 的项目的集合的数量。这种期望基于https://docs.djangoproject.com/en/1.5/topics/db/queries/#lookups-that-span-relationships上的文档,其中有一个示例说“此示例检索所有 Entry 对象一个名为“Beatles Blog”的博客”。
但是,上面的调用实际上打印了“6”,这是具有 flag=True 的 Item 记录的数量。但是,返回的实际对象是 Collection 对象。似乎它多次返回同一个 Collection 对象,对于每个带有 flag=True 的对应项记录一次。这可以通过以下方式确认:
queryset = Collection.objects.filter(item__flag=True)
queryset[0] == queryset[1]
打印 True。
这是正确的行为吗?如果是这样,理由是什么?如果这是预期的,文档可以被解释为严格正确,但它没有说每个对象可以多次返回。
这是一个相关示例,这似乎是非常令人惊讶(或完全错误)的行为。在自定义模型管理器添加了 exclude() 调用并且调用者随后添加了 filter() 的情况下,我发现了这一点:
from django.db.models import Count
[coll.count for coll in Collection.objects.filter(item__flag=True).annotate(count=Count("item"))]
[coll.count for coll in Collection.objects.exclude(item=None).filter(item__flag=True).annotate(count=Count("item"))]
第一种情况打印“[2,4]”,但第二种情况打印“[8,16]”!!!
填充函数:
def populate():
Collection.objects.all().delete()
collection = Collection()
collection.save()
item = Item(collection=collection, flag=True)
item.save()
item = Item(collection=collection, flag=True)
item.save()
item = Item(collection=collection, flag=False)
item.save()
item = Item(collection=collection, flag=False)
item.save()
collection = Collection()
collection.save()
item = Item(collection=collection, flag=True)
item.save()
item = Item(collection=collection, flag=True)
item.save()
item = Item(collection=collection, flag=True)
item.save()
item = Item(collection=collection, flag=True)
item.save()
collection = Collection()
collection.save()
item = Item(collection=collection, flag=False)
item.save()
item = Item(collection=collection, flag=False)
item.save()
item = Item(collection=collection, flag=False)
item.save()
item = Item(collection=collection, flag=False)
item.save()