Фильтр глубоких вложенных related_set в Django
Существует две модели:
class Subject(Model):
categories = ManyToManyField(Category, related_name='subjects')
class Category(Model):
parent = ForeignKey('self', related_name='subcategories')
Это должно быть переведено в следующий вывод остатков:
[
{
...,
"categories": [
{"subcategories": [{}, {} ... {}]},
{"subcategories": [{}, {} ... {}]}
],
},
{
...,
"categories": [
{"subcategories": [{}, {} ... {}]},
{"subcategories": [{}, {} ... {}]}
],
}
]
Проблема заключается в том, чтобы иметь набор подкатегорий для каждой категории, подкатегорий, которые находятся в отношении "многие ко многим" с предметом-предком.
Пока что я думаю, что queryset должен быть примерно таким:
Subject.objects.prefetch_related(
Prefetch(
lookup="categories",
queryset=Category.objects.filter(parent__isnull=True)
.prefetch_related(
Prefetch(
lookup="subcategories",
queryset=Subquery(
Category.objects.filter(
parent__pk=OuterRef("pk"),
subjects__id__in=OuterRef(OuterRef("pk")),
)
)
)
)
.distinct(),
),
)
Но это дает ошибку:
AttributeError: 'Subquery' object has no attribute '_chain'
Что не так с кверисетом. Как правильно поступить?
То, что вы пытаетесь сделать в одном операторе, не является ни аккуратным, ни эффективным. Лучшим подходом будет использование рекурсивной функции и последующая организация ответа. Вы можете взглянуть на следующее.
def get_sub_categories(category):
"""
This is a function which we are using recursively to get all subcategories for a catefgory
"""
category_data = {'name': category.name}
subcategories = category.subcategories.all()
if subcategories:
category_data['subcategories'] = [get_sub_categories(subcategory) for subcategory in subcategories]
return category_data
Используя вышеуказанную функцию, вы можете получить желаемый ответ на заданную тему.
subject = Subject.objects.get(id=subject_id)
categories = subject.categories.all()
data = [get_sub_categories(category) for category in categories]
Ваши данные будут выглядеть следующим образом, далее вы можете внести коррективы, чтобы получить необходимые поля в соответствии с вашими потребностями
[
{
"name": "Government Exam",
"subcategories": [
{
"name": "SSC",
"subcategories": [
{
"name": "Physical",
"subcategories": [
{
"name": "Body 1"
},
{
"name": "Body 2"
}
]
},
{
"name": "Written",
"subcategories": [
{
"name": "Socialogy"
},
{
"name": "Enviromental"
}
]
}
]
},
{
"name": "NDA"
}
]
}
]