Поиск аннотированного списка братьев и сестер в Django
У меня есть простая база данных с двумя моделями, которые определяют отношения родитель-ребенок. В ней ребенок может иметь два возможных пола, "Мужской" или "Женский".
class Parent(models.Model):
id = models.UUIDField(primary_key=True, editable=False, unique=True, )
name = models.CharField(max_length=64)
MALE = "MALE"
FEMALE = "FEMALE"
class Child(models.Model):
id = models.UUIDField(primary_key=True, editable=False, unique=True, )
name = models.CharField(max_length=64)
parent = models.ForeignKey(
Parent,
null=True,
on_delete=models.SET_NULL)
GENDER = [
(MALE, 'Male'),
(FEMALE, 'Female'),
]
status = models.CharField(
max_length=8,
choices=GENDER
)
Для целей данного вопроса родитель будет иметь только ноль или один ребенок мужского пола и ноль или один ребенок женского пола. (Хотя это и не закреплено в определении модели базы данных)
Я хотел бы получить аннотированный запрос, который возвращает все Parent
объекты, аннотированные с их дочерними мужскими и женскими детьми. Я не могу понять, как это сделать: Я могу получить список всех родителей, всех детей мужского пола и всех детей женского пола, но я не знаю, как собрать их вместе, чтобы нужные дети были с нужным родителем.
Это далеко, как я понял:
annotated_parent_set = Parent.objects.get_queryset()
brothers = Child.objects.filter(gender=MALE)
sisters = Child.objects.filter(gender=FEMALE)
annotated_parent_set = annotated_parent_set.annotate(
brother=F(???))
)
annotated_parent_set = annotated_parent_set.annotate(
sister=F(???))
)
Как мне теперь объединить их, чтобы получить нужную мне аннотацию?
Вам не нужно аннотировать это, вы можете .prefetch_related(…)
[Django-doc] это с:
annotated_parent_set = Parent.objects.prefetch_related('child_set')
или если вы хотите использовать .brothers.all()
и .sisters.all()
, то вы можете работать с двумя Prefetch
объектами [Django-doc]:
from django.db.models import Prefetch
annotated_parent_set = Parent.objects.prefetch_related(
Prefetch('child_set', Child.objects.filter(status=MALE), to_attr='brothers'),
Prefetch('child_set', Child.objects.filter(status=FEMALE), to_attr='sisters')
)