Есть ли способ динамически задавать кверисет для вложенных отношений (вложенный класс сериализатора) в django rest framework

Предположим, что у нас есть две модели:

class Chapter(models.Model):
    title = models.CharField(max_length=128)
    owner = models.ForeignKey(User, on_delete=models.CASCADE)


class Post(models.Model):
    title = models.CharField(max_length=128)
    body = models.TextField()
    is_archived = models.BooleanField(default=False)
    chapter = models.ForeignKey(Chapter, on_delete=models.CASCADE)

И набор представлений по умолчанию ModelViewSet для Chapter модели:

class ChapterViewSet(viewsets.ModelViewSet):
    queryset = Chapter.objects.all()
    serializer_class = ChapterSerializer

Ключевым моментом является то, что ChapterSerializer выполняет вложенную сериализацию, используя PostSerializer для обеспечения post_set ключа в ответе.

class PostSerializer(serializers.HyperlinkedModelSerializer):
    detail_url = HyperlinkedIdentityField(view_name='post-detail', read_only=True)

    class Meta:
        fields = ['id', 'title', 'is_archived', 'detail_url']
        model = Post

class ChapterSerializer(serializers.ModelSerializer):
    post_set = PostSerializer(read_only=True, many=True)

    class Meta:
        model = Chapter
        fields = ['id', 'title', 'owner', 'post_set']

Вопрос в том, как я могу динамически определить набор запросов для этого вложенного PostSerializer. Например, когда пользователь делает запрос GET, я хочу включить только те посты, которые не архивируются (поле is_archived установлено в False), если пользователь, который сделал запрос, не является владельцем Chapter (request.user != current_chapter.owner). Есть ли способ добиться этого?

Вы можете использовать prefetch_related для предварительной выборки результатов, используемых вложенным сериализатором, эта предварительная выборка может быть отфильтрована с помощью объекта Prefetch, который затем отфильтрует вложенные результаты

class ChapterViewSet(viewsets.ModelViewSet):
    queryset = Chapter.objects.all()
    serializer_class = ChapterSerializer

    def get_queryset(self):
        queryset = super().get_queryset()
        return queryset.prefetch_related(
            Prefetch('post_set', queryset=Post.objects.filter(is_archived=False))
        )

В методе get_queryset вам придется выполнять эту предварительную выборку динамически, доступ к текущему запросу можно получить через self.request

Вернуться на верх