如何在 Django 序列化器上过滤外键关系?

问题描述 投票:0回答:1

如何使用反向外键关系生成左外连接查询并将其映射到嵌套序列化程序?我想过滤多个外键的结果。

models.py

class Question(models.Model):
    question_name = models.CharField(max_length=1024) 

class Paper(models.Model):    
    paper_name = models.CharField(max_length=128)

class Answer(models.Model):
    score = models.IntegerField()
    question_id = models.ForeignKey(Question, related_name='answer_questions')
    paper_id = models.ForeignKey(Paper, related_name='answer_papers')
 class Meta:
    unique_together = ("question_id", "paper_id")

serializers.py

class PaperSerializer(serializers.ModelSerializer):        
    class Meta:
        fields = ('id', 'paper_name')
        model = Paper            

class AnswerSerializer(serializers.ModelSerializer):
    class Meta:
        fields = ('id', 'score', 'question_id', 'paper_id')
        model = Answer    

class QuestionSerializer(serializers.ModelSerializer):
    answer_questions = AnswerSerializer(many=True, allow_null=True)    
    class Meta:
        fields = ('id', 'question_name', 'answer_questions')
        model = Question

views.py

class QuestionList(generics.ListAPIView):      
    def get_queryset(self):
        paper_id = self.kwargs['pk']
        queryset = Question.objects.filter(answer_questions__paper_id=paper_id, answer_questions__question_id=F('id'))
        return queryset

    serializer_class = QuestionSerializer

我的网址是 本地主机/论文/1/问题/

预期输出: (1) 仅包含 对应的 question_id 和 paper_id(单个答案对象) 答案对象的所有问题列表。 (2) 列表应包括所有问题,无论是否回答(如果问题未回答,应返回答案对象为空的问题)即左外连接

[
    {
        "id": 1,
        "question_id": 1,
        "answer_questions": [
            {
                "id": 24,
                "score": 5,
                "question_id": 1,
                "paper_id": 1
            },
            {
                "id": 27,
                "score": 8,
                "question_id": 1,
                "paper_id": 2
            },
            {
                "id": 28,
                "score": 6,
                "question_id": 1,
                "paper_id": 3
            }
        ]
    }
]    

电流输出: (1) 我得到了特定 question_id 包括所有 paper_ids 的多个答案对象。即对于 question_id = 1 和 paper_id = 2,我的输出显示带有 question_id = 1 不过滤 paper_id 答案对象的问题。 (2) 只回答问题(因为query是inner join query)

[
    {
        "id": 1,
        "question_id": 1,
        "answer_questions": [
            {
                "id": 24,
                "score": 5,
                "question_id": 1,
                "paper_id": 1
            }
        ]
    }
]

如果这不是一个好的实施方式,请提出更好的优化方法。

django django-rest-framework foreign-keys django-orm django-serializer
1个回答
3
投票

我想如果你稍微改变

get_quesyset()
方法,你会得到想要的输出。

class QuestionList(generics.ListAPIView):
    def get_queryset(self):
        return Question.objects.all()

    serializer_class = QuestionSerializer

当您访问

QuestionList list api
时,您将获得如下输出

[
    {
        "id": 4,
        "question_name": "qus-1",
        "answer_questions": [
            {
                "id": 5,
                "score": 50,
                "question_id": 4,
                "paper_id": 4
            },
            {
                "id": 6,
                "score": 10,
                "question_id": 4,
                "paper_id": 5
            }
        ]
    },
    {
        "id": 5,
        "question_name": "qus-2",
        "answer_questions": []
    },
    {
        "id": 6,
        "question_name": "que-3",
        "answer_questions": [
            {
                "id": 7,
                "score": 342,
                "question_id": 6,
                "paper_id": 4
            }
        ]
    }
]

更新-1

按以下方式更改您的序列化器

class QuestionSerializer(serializers.ModelSerializer):
    answer_questions = serializers.SerializerMethodField()

    def get_answer_questions(self, question):
        paper_id = self.context['view'].kwargs.get('paper_id')
        return AnswerSerializer(question.answer_questions.filter(paper_id=paper_id), many=True).data

    class Meta:
        fields = ('id', 'question_name', 'answer_questions')
        model = Question
© www.soinside.com 2019 - 2024. All rights reserved.