Stack Overflow на русском Asked by Sh VavilenT on December 30, 2021
Хочу отфильтровать по параметрам запроса (по id).
К примеру: http://…/themes/?category=1&level=1
model.py
class Themes(models.Model):
category = models.ForeignKey(Categories, on_delete=models.CASCADE)
level = models.ManyToManyField(Level)
views.py
class ThemesListView(generics.ListAPIView):
serializer_class = ThemesListSerializer
def get_queryset(self):
queryset = Themes.objects.all()
category = self.request.query_params.get('category')
level = self.request.query_params.get('level')
if category:
queryset = queryset.filter(category_id=category)
if level:
queryset = queryset.filter(level=level)
return queryset
Ожидаю:
{
"id": 1,
"category": 1,
"level": [
1
]
}
Получаю:
{
"id": 1,
"category": 1,
"level": [
1,
2
]
}
Подскажите пожалуйста, как можно исправить код?
Проблема возникает из-за того, что все предикаты добавленные в queryset
с помощью filter
, используется только для фильтрации объектов, которые возвращает queryset
, т.е. в даном случае Themes
.
Это значит, что выполняется запрос "верни мне все Themes, у которых есть такой то level". Данные для модели Level
достаются отдельными запросами уже когда происходит сериализация Themes
и идет доступ к полю level
.
Чтоб это исправить нужно сконфигурировать запрос так, чтоб ассоциированные Level
доставались в том же запросе (ну и при этом наложить фильтр, который укажет выбирать не все). Для этого нужно воспользоваться prefetch_related как-то так:
from django.db.models import Prefetch
...
if level:
# тут предполагается, что фильтруем по полю id в Level
queryset = queryset.prefetch_related(
Prefetch('level', queryset=Level.objects.filter(id=level)))l
Answered by Roman Konoval on December 30, 2021
Get help from others!
Recent Questions
Recent Answers
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP