Сериализация внешнего ключа внешнего ключа (DRF) - PullRequest
0 голосов
/ 05 февраля 2019

У меня есть 3 уровня моделей: Сессия вопросов (содержит кучу вопросов), Вопрос и ответ.Все они связаны через ForeignKey:

class QuestionSession(models.Model):
    name = models.CharField(max_length=100)

class Question(models.Model):
    description = models.CharField(max_length=400)
    question_type = models.CharField(max_length=50)
    answers = models.PositiveIntegerField(default=0)
    answers_to_close = models.PositiveIntegerField(default=3)
    answered = models.BooleanField(default=False)
    choices = models.CharField(
        max_length=1000, blank=True, null=True, default=None)

    question_session = models.ForeignKey(
        QuestionSession,
        on_delete=models.CASCADE,
        related_name='questions',
        blank=True,
        null=True,
        default=None
    )

class Answer(models.Model):
    question = models.ForeignKey(
        Question,
        related_name='answers_list',
        on_delete=models.CASCADE)
    answer = models.CharField(max_length=500)
    created_at = models.DateTimeField(auto_now_add=True)

И мой serializers.py:

class QuestionSessionSerializer(serializers.ModelSerializer):
project = ProjectSerializer()

class Meta:
    model = QuestionSession
    fields = [
        'id',
        'questions',
        'project'
    ]


class QuestionSerializer(serializers.ModelSerializer):
    question_session = QuestionSessionSerializer()

class Meta:
    model = Question
    fields = [
        'id',
        'description',
        'question_type',
        'created_at',
        'answers',
        'answers_to_close',
        'answered',
        'question_session',
        'choices',
        'answers_list'
    ]


class AnswerSerializer(serializers.ModelSerializer):
    question = QuestionSerializer()

class Meta:
    model = Answer
    fields = [
        'question',
        'answer',
        'created_at'
    ]

Я легко могу получить объекты вопросов из QuestionSession с помощью:

QuestionSession.objects.get (pk = 1) .questions.all ()

И я также могу получить ответы со следующим:

QuestionSession.objects.get (pk = 1) .questions.objects.get (pk = 1) .answers_list.all ()

Но когда я отправляю эти данные через Response, он отправляет только идентификаторы ответов вместообъекты.Мое мнение:

    def get(self, request, **kwargs):
    """Fetch a single session"""

    session_id = kwargs['session_id']

    questions = QuestionSerializer(
        QuestionSession.objects.get(
            pk=session_id).questions.filter(answered=False),
        many=True
    )

    return Response({
        'session': session_id, 'questions': questions.data
    })

Как изменить сериализаторы так, чтобы они передавали объекты ответа вместо идентификатора?

Ответы [ 2 ]

0 голосов
/ 07 февраля 2019

Использование глубины решит проблему, но попробуйте использовать prefetch_related и select_related.Это будет наилучшей практикой и не уменьшит количество запросов (ответ на запрос быстрее).

Для вашей проблемы используйте select_related, это решит проблему.Для дальнейших ссылок или сомнений используйте эту ссылку: https://medium.com/quant-five/speed-up-django-nested-foreign-key-serializers-w-prefetch-related-ae7981719d3f

PS: Для проверки используйте панель инструментов Django Debug, она объяснит, сколько подзапросов выполняется в фоновом режиме.

0 голосов
/ 05 февраля 2019

Вы пытались указать вложенный глубина на вашем сериализаторе?:

class QuestionSerializer(serializers.ModelSerializer):
    question_session = QuestionSessionSerializer()

    class Meta:
        model = Question
        fields = [
            'id',
            'description',
            'question_type',
            'created_at',
            'answers',
            'answers_to_close',
            'answered',
            'question_session',
            'choices',
            'answers_list'
        ]
        depth = 1
...