В вашем конкретном случае c я предполагаю, что лучше использовать аннотацию вместо предварительной выборки:
from django.db.models import Count, Q
cities = City.objects
.annotate(bank_count=Count("street", filter=Q(street__building_id=1)))
.annotate(cinema_count=Count("street", filter=Q(street__building_id=2)))
.annotate(church_count=Count("street", filter=Q(street__building_id=3)))
Теперь вы можете напрямую использовать bank_count
, cinema_count
и church_count
атрибуты:
for city in cities:
print(city.bank_count)
print(city.cinema_count)
print(city.church_count)
Если вы хотите использовать prefetch_related
, вам нужно использовать Prefetch
объект. Это позволяет фильтровать предварительно выбранные объекты:
City.objects.prefect_related(
Prefetch("street_set", queryset=Street.objects.filter(building_id=1), to_attr='has_bank'),
Prefetch("street_set", queryset=Street.objects.filter(building_id=2), to_attr='has_cinema'),
Prefetch("street_set", queryset=Street.objects.filter(building_id=3), to_attr='has_church')
)
Примечание. Аргумент to_attr
позволяет предварительно выбирать объекты одной модели с разными фильтрами для разных атрибутов. Так что вы можете сделать сейчас:
for city in cities:
print(city.has_bank)
print(city.has_cinema)
print(city.has_church)