我觉得我对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",即至少有一个Item的flag为True的Collection数量。这个期望基于文档https://docs.djangoproject.com/en/1.5/topics/db/queries/#lookups-that-span-relationships中的一个例子:"该示例检索所有具有名称为'Beatles Blog'的Blog的Entry对象"。
然而,上述调用实际上打印了"6",这是拥有flag=True
的Item记录数量。虽然实际返回的是Collection对象,但似乎它对应于每个具有flag=True
的相应Item记录一次返回相同的Collection对象。可以通过以下方式确认:
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()