DRF ManytoMany filtering on related model, in subquery?

Viewed 119

There are two models, a Page model and a Banner model, which are manyToMany related. The parameters API is twitched, which returns a list of pages and banners for each page. The Banner model has a field is_show by which you need to additionally filter the list of banners, i.e. in the admin panel, the banner can be selected for the model, but if is_show = False, then you do not need to return it to the API.

views

class PagesListView(generics.ListAPIView,
                   viewsets.GenericViewSet):
    queryset = Page.objects.all()
    serializer_class = PageSerializer

models

class Banner(models.Model):
    title = models.CharField(verbose_name='Заголовок', max_length=255, null=True, blank=True)
    is_show = models.BooleanField(verbose_name='Управление отображением', null=False)
    pages = models.ManyToManyField(
        Page, blank=True, related_name='banners')

class Page(models.Model):
    name = models.CharField(max_length=255, null=True, blank=True)

serializers

class BannerSerializer(serializers.ModelSerializer):

    class Meta:
        model = Banner
        fields = '__all__'


class PageSerializer(serializers.ModelSerializer):
     banners = BannerSerializer(read_only=True, many=True)

     class Meta:
        model = Page
        fields = '__all__'

The question is how to filter Banner by is_show field?

If you just override the queryset for the view like this:

queryset = Page.objects.filters(banners__is_show=True)

then this is not the desired behavior. In this way, I am filtering the Page list, and I need to "wedge" into filtering the Banner list.

1 Answers

You can do it using related_name with prefetch_related

For ex:

queryset = Page.objects.all().prefetch_related(
        Prefetch('banners', queryset=Banner.objects.filter(is_show=True)))
Related