带有查找字段的嵌套模型外键上的 Django JOIN

Posted

技术标签:

【中文标题】带有查找字段的嵌套模型外键上的 Django JOIN【英文标题】:Django JOIN on nested model Foreign key with look up field 【发布时间】:2018-03-12 19:00:08 【问题描述】:

我在 Django Rest Framework 中使用 2 个模型

class Questions(models.Model):
    question = models.TextField()
    answer = models.TextField()
    timestamp = models.DateTimeField(auto_now_add=True)
    categories = models.ForeignKey(Categories, related_name="cat_questions", on_delete=models.CASCADE)


class QuestionnaireResult(models.Model):
    patient_info = models.ForeignKey(PatientInfo, related_name="+", on_delete=models.CASCADE)
    questions = models.ForeignKey(Questions, related_name="result_questions", on_delete=models.CASCADE)
    answer_given = models.TextField()
    timestamp = models.DateTimeField(auto_now_add=True)

两者都有序列化器

class QuestionnaireResultSerailizer(serializers.ModelSerializer):
    class Meta:
        model = QuestionnaireResult
        fields = '__all__'


class QuestionsSerializer(serializers.ModelSerializer):
    result_questions = QuestionnaireResultSerailizer(many=True)

    class Meta:
        model = Questions
        fields ='__all__'

观看次数:

class QuestionsViewSet(viewsets.ModelViewSet):
    queryset = Questions.objects.all()
    serializer_class = QuestionsSerializer


class QuestionnaireResultViewSet(viewsets.ModelViewSet):
    queryset = QuestionnaireResult.objects.all()
    serializer_class = QuestionnaireResultSerializer
    filter_backends = (filters.DjangoFilterBackend,)
    filter_fields = ['patient_info']

使用 URL - http://localhost:9000/api/questions/1,它根据 question_id = 1 给出结果,result_questions 仅包含那些具有 questions id == 1。没错。


    "id": 1,
    "result_questions": [
        
            "id": 1,
            "answer_given": "no",
            "timestamp": "2017-10-01T12:28:19.770454Z",
            "patient_info": 1,
            "questions": 1
        ,
        
            "id": 4,
            "answer_given": "no",
            "timestamp": "2017-10-01T13:13:19.658930Z",
            "patient_info": 2,
            "questions": 1
        
    ],
    "question": "digestive ques 1",
    "answer": "yes",
    "timestamp": "2017-09-30T17:04:59.143857Z",
    "categories": 1

但上面 nested json (result_questions) 返回 all patient_info 其中有 questions id == 1 但我想添加一个更多过滤器(患者信息) 就可以了。我只想要那些我想通过传递为查找字段来检索的患者信息

我想要的是那个。假设,我使用这个网址http://localhost:9000/api/questions/1?patient_info=1

它返回具有 question_id == 1 和 Patient_info ==1 的响应。因此,响应应该是:


    "id": 1,
    "result_questions": [
        
            "id": 1,
            "answer_given": "no",
            "timestamp": "2017-10-01T12:28:19.770454Z",
            "patient_info": 1,
            "questions": 1
        
    ],
    "question": "digestive ques 1",
    "answer": "yes",
    "timestamp": "2017-09-30T17:04:59.143857Z",
    "categories": 1

【问题讨论】:

也请发表您的看法 @JahongirRahmonov 已发布视图。 【参考方案1】:

你可以试试serializermethodfield

class QuestionsSerializer(serializers.ModelSerializer):
    result_questions = serializers.SerializerMethodField()

    class Meta:
        model = Questions
        fields ='__all__'

    def get_result_questions(self, obj):
        qs = obj.result_questions.all()
        request = self.context.get('request')
        patient_info = request.GET.get('patient_info')
        if patient_info:
            qs = qs.filter(patient_info=patient_info)
        return QuestionnaireResultSerailizer(qs, many=True).data

【讨论】:

谢谢。有效。你能帮我找到学习django rest框架的交互式教程吗? 很高兴为您提供帮助。我是通过django-angularjs-tutorial开始学习drf的 有一个问题。如果我使用serializers.SerializerMethodField()。我不能做POST 请求。它抛出错误 - "errors": "'NoneType' object has no attribute 'GET'" 对于发布操作,如果使用 SerializerMethodField,则需要覆盖 create 方法 或尝试理解@neverwalkaloner 的答案并修复错误【参考方案2】:

在视图中尝试在get_object 方法中使用prefetch_related

def get_object(self, pk):
    try:
        return Questions.objects.prefetch_related(Prefetch('result_questions',  
            queryset=QuestionnaireResult.objects.filter(id=self.request.GET.get('patient_info')))).get(pk=pk)
    except Questions.DoesNotExist:
        raise Http404

【讨论】:

它抛出 - get_object() takes exactly 2 arguments (1 given)

以上是关于带有查找字段的嵌套模型外键上的 Django JOIN的主要内容,如果未能解决你的问题,请参考以下文章

django模型中, 外键字段使用to_filed属性 指定到所关联主表的某个字段

在 django admin 中使用外键访问另一个模型字段

带有嵌套序列化程序的 Django 反向外键给出了多个结果

Django Rest Framework:具有通用外键的可写嵌套序列化程序

两个外键字段,正好一个被设置为一个值,另一个在 MySQL 数据库的 django 模型中为空

Django - 使用 2 个嵌套外键复制模型实例