TransWikia.com

Как отфильтровать по параметрам запроса, отношение многим ко многим

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
    ]
}

Подскажите пожалуйста, как можно исправить код?

One Answer

Проблема возникает из-за того, что все предикаты добавленные в 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

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP