Django Rest Framework: Показать объект только для конкретного выбора - PullRequest
0 голосов
/ 15 ноября 2018

У меня есть этот сериализатор:

class PublicProgramSerializer(serializers.ModelSerializer):
    class Meta:
        model = Program
        fields = (
            ...
            'questions'
        )

    questions = CustomQuestionSerializer(source="custom_questions", many=True)

И

class CustomQuestionSerializer(serializers.ModelSerializer):

    class Meta:
        model = CustomQuestion
        fields = (
            'label',
            'type',
            'scope'
        )

Теперь «сфера» - это поле выбора с 3 вариантами: REGISTRATION, PARTICIPANT, EVENT, и я хочу сериализовать только пользовательские вопросы, для которых задана область действия REGISTRATION. Как мне этого добиться?

Спасибо за любой ответ!

Редактировать: Модели:

Program.py

class Program(models.Model):
    created = models.DateTimeField(u'Created', auto_now_add=True)
    name = models.CharField(u'Program Name', max_length=100)
    description = models.TextField(u'Description', help_text=mark_safe(MARKDOWN_HELP_STRING), blank=True, null=True)

и т. Д. Нет ничего особенного в Программе

CustomQuestion.py

class CustomQuestion(models.Model):
    class Meta:
        order_with_respect_to = 'program'

    SCOPE_REGISTRATION = "registration"
    SCOPE_PARTICIPANT = "participant"
    SCOPE_EVENT = "event"

    SCOPE_CHOICES = (
        (SCOPE_REGISTRATION, "Registration"),
        (SCOPE_PARTICIPANT, "Participant"),
        (SCOPE_EVENT, "Event"),
    )

    program = models.ForeignKey("Program", related_name="custom_questions")
    scope = models.CharField(
        verbose_name="Scope",
        choices=SCOPE_CHOICES,
        null=False,
        max_length=50
    )
    description = models.CharField(
        verbose_name=u"Description",
        null=True, blank=True,
        max_length=100
    )
    label = models.CharField(
        verbose_name="Label",
        null=False, blank=False,
        max_length=80
    )

И набор для программы:

class ProgramList(generics.ListAPIView):
    model = Program
    permission_classes = (AllowAny,)
    serializer_class = PublicProgramSerializer
    queryset = Program.objects.exclude(visibility='hidden').filter(is_archived=False)

    def get(self, request, *args, **kwargs):
        programs = self.get_queryset()
        data = self.serializer_class(programs, context={'request': request}, many=True).data
        response = Response(data)
        response['Cache-Control'] = 'no-cache'
        return response

    def get_queryset(self):
        scope = self.request.GET.get('scope')
        if scope and scope in CustomQuestion.SCOPE_CHOICES:
            return Program.objects.filter(participant_questions__scope=scope)
        else:
            return Program.objects.all()

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Ну, я нашел решение, которое очень хорошо работает для меня:

Я не знал, что вы можете использовать пользовательский метод в качестве source в методе сериализатора, например:

questions = CustomQuestionSerializer(source="get_participant_questions", many=True)

Итак, я только что создал get_participant_questions метод в моем program.py, где я отфильтровал эти точные вопросы:

def get_participant_questions(self):
        return self.custom_questions.filter(scope=CustomQuestion.SCOPE_PARTICIPANT)

и т. Д. Мой API показал мне именно то, что я хотел.

Большое спасибо @Bast, твой ответ помог мне найти этот путь:)

0 голосов
/ 15 ноября 2018

Создайте метод под названием "get_queryset" в вашем наборе, как это

class ProgramViewSet(viewsets.ViewSet):
    serializer_class = ProgramSerializer

    def get_queryset(self):
        scope = self.request.GET.get('scope')
        if scope and scope in CustomQuestion.SCOPE_CHOICE:
            return Program.objects.filter(questions__scope=scope)
        else
            return Program.objects.all()

    def list(self, request):
        paginator = LimitOffsetPagination()
        if request.GET.get('limit'):
            page = paginator.paginate_queryset(self.get_queryset(), request)
            serializer = self.serializer_class(page, many=True)
            if page is not None:
                return paginator.get_paginated_response(serializer.data)
        else:
            serializer = self.serializer_class(self.get_queryset(), many=True)
        return response.Response(serializer.data)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...