Я думаю, что мне не хватает чего-то очень элементарного и фундаментального в том, как должен работать метод filter() Django.Django filter() на поле родственной модели
с использованием следующих моделей:
class Collection(models.Model):
pass
class Item(models.Model):
flag = models.BooleanField()
collection = models.ForeignKey(Collection)
и данными, полученными от вызова функции Заселите() в нижней части вопроса, Попробуйте выполнить следующие действия в ./manage.py оболочки:
len(Collection.objects.filter(item__flag=True))
Мое предположение состояло в том, что это напечатало бы «2», то есть количество коллекций, имеющих хотя бы один элемент с флагом = True. Это ожидание было основано на документации по адресу https://docs.djangoproject.com/en/1.5/topics/db/queries/#lookups-that-span-relationships, в которой приведен пример: «В этом примере извлекаются все объекты Entry с блоком, чье имя« Beatles Blog »».
Однако вызов выше на самом деле печатает «6», это число записей элементов, имеющих флаг = True. Фактически возвращенные объекты - объекты Collection. Кажется, что он возвращает один и тот же объект Collection несколько раз, один раз для каждой записи элемента с флагом = True. Это может быть подтверждено:
queryset = Collection.objects.filter(item__flag=True)
queryset[0] == queryset[1]
который печатает True.
Это правильное поведение? Если да, то в чем причина? Если это то, что ожидается, документация может быть истолкована как строго правильная, но она не позволяет утверждать, что каждый объект может быть возвращен несколько раз.
Вот пример, который кажется очень удивительным (или просто неправильным) поведением. Он поймал меня в случае, когда исключение() вызов был добавляемый менеджером пользовательских моделей и вызывающая затем добавить фильтр():
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]" !!!
Populate функция:
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()