【问题标题】:How to combine two querysets from two models? Django Rest Framework如何组合来自两个模型的两个查询集? Django 休息框架
【发布时间】:2022-02-03 03:39:00
【问题描述】:

我有两个模型

class Answer(models.Model):
    answer = models.TextField()
    created_at = models.DateTimeField(editable=False, default=timezone.now)
    updated_at = models.DateTimeField(default=timezone.now)
    user = models.ForeignKey('users.CustomUser', on_delete=models.PROTECT)
    question = models.ForeignKey('Question', on_delete=models.PROTECT)
    number_of_points = models.IntegerField(default=0)
    moderate_status = models.BooleanField(default=False)

class Question(models.Model):
    question_subject = models.TextField()
    question_text = models.TextField(default=None, null=True, blank=True)
    slug = models.SlugField(max_length=128, unique=True, null=False, editable=False)
    created_at = models.DateTimeField(editable=False, default=timezone.now)
    updated_at = models.DateTimeField(default=timezone.now)
    user = models.ForeignKey('users.CustomUser', on_delete=models.PROTECT)
    animal = models.ForeignKey('animals.Animal', on_delete=models.PROTECT)

序列化器.py

class QuestionDetailSerializer(serializers.ModelSerializer):
    answers = serializers.PrimaryKeyRelatedField(many=True, read_only=True)

    class Meta:
        model = Question
        fields = '__all__'

views.py

class QuestionsDetailView(generics.ListAPIView):
    queryset = Question.objects.all()
    serializer_class = QuestionsSerializer

    def get_queryset(self):
        return super().get_queryset().filter(
            id=self.kwargs['pk']
        )

url.py

path('questions/<int:pk>', QuestionsDetailView.as_view()),

我想组合 2 个查询集,一个已经通过 url 中提供的 pk 过滤问题,而我想提供的另一个查询集是 Answer.objects.all().filter(question__id='pk ')。本质上,我想显示所有问题以及特定问题的答案。

【问题讨论】:

    标签: python django django-rest-framework django-views


    【解决方案1】:

    我强烈建议在任何可能的地方使用关系。

    models.py 中添加related_nameAnswer.question

    class Answer(models.Model):
        ...
        question = models.ForeignKey('Question', on_delete=models.PROTECT, related_name='answers')
    

    如果id在序列化器中足够了,那么在serializers.py中:

    class QuestionDetailSerializer(serializers.ModelSerializer):
        # this is not needed anymore: answers = serializers.PrimaryKeyRelatedField(many=True, read_only=True)
    
        class Meta:
            model = Question
            fields = ['question_subject ', 'question_text', ..., 'answers`]
    

    但是你也可以创建一个model 的函数,你可以用类似的方式包含它:

    class Question(models.Model):
        ...
        def get_answers(self):
            return [answer.answer for answer in self.answers.all()]    # it will return a list of TextFields of answers
    

    serializers.py:

    class QuestionDetailSerializer(serializers.ModelSerializer):
        class Meta:
            model = Question
            fields = ['question_subject ', 'question_text', ..., 'get_answers`]
    

    【讨论】:

      【解决方案2】:

      您不会完全组合来自不同表的 2 个查询集。但是你可以使用嵌套的序列化器。

      class AnswerSerializer(serializers.ModelSerializer):
      
          class Meta:
              model = Anwser
              fields = ['id', ...]
      
      class QuestionDetailSerializer(serializers.ModelSerializer):
          answer_set = AnswerSerializer(many=True, read_only=True)
      
          class Meta:
              model = Question
              fields = ['id', ..., 'answer_set']
      
      # OR
      
      
      class QuestionDetailSerializer(serializers.ModelSerializer):
      
          class Meta:
              model = Question
              fields = ['id']
          
          def to_representation(self, instance):
              data = super().to_representation(instance)
              data['answers'] = AnswerSerializer(many=True, instance=instance.anwser_set.all()).data
              return data
      
      

      【讨论】:

        猜你喜欢
        • 2018-03-10
        • 2018-06-27
        • 2018-03-30
        • 2010-09-23
        • 1970-01-01
        • 2014-05-09
        • 2020-04-19
        • 1970-01-01
        • 2017-06-04
        相关资源
        最近更新 更多