【问题标题】:DRF nested serialization without raw sql query没有原始 sql 查询的 DRF 嵌套序列化
【发布时间】:2021-12-14 00:39:01
【问题描述】:

我已经被这个问题困扰了好几天了。尝试了不同的方法,但没有成功。我有两个课程 - Poll 和 PollAnswer。他们在这里:

class Poll(Model):
    title = CharField(max_length=256)
class PollAnswer(Model):
    user_id = CharField(max_length=10)
    poll = ForeignKey(Poll, on_delete=CASCADE)
    text = CharField(max_length=256)

获取投票列表的正确方法是什么,其中 used_id 的答案等于具有该用户答案的​​嵌套列表的某个字符串?像这样:

{
    'poll_id': 1,
    'answers' : {
        'user1_answer1: 'answer_text1',
        'user1_answer2: 'answer_text2',
        'user1_answer3: 'answer_text3',    
    },
}

如果这是一个简单的问题,我可能需要一些关于 django orm 的好的指南。

我尝试的第一件事是制作序列化程序的方法(继承自 drf 的 ModelSerializer),但收到一个错误,即此类不能有这样的方法。之后,我尝试将序列化程序的字段与 ForeignKey 一起使用,但将民意调查嵌套在答案中。现在我相信我可以制作 Polls.objects.raw('some_sql_query') 但这可能不是最好的方法。

【问题讨论】:

  • 我认为使用DictField 应该可以做到这一点,但由于它们是动态的,因此需要一些额外的工作来创建密钥。为什么不将答案创建一个数组并使用包含用户 ID 和答案的嵌套对象?
  • 啊,所以我将有一个带有轮询的序列化程序,我可以从 PollAnswer.objects.filter(user_id=user_id) 获得,然后使用 PollAnswer.objects.filter(poll_id=Poll. id).filter(user_id=user_id) 对吗?
  • 我认为这听起来不错。
  • 嗨,你找到答案了吗?
  • 我还没试过。过几天再试。

标签: django django-rest-framework django-orm


【解决方案1】:

文档中描述了您的问题(也是最佳实践)。 您可以使用嵌套序列化程序:

https://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers

否则,如果您想按照您的描述保留嵌套答案: 我会使用序列化方法字段

https://www.django-rest-framework.org/api-guide/fields/#serializermethodfield

然后对你的答案做一个小循环......并返回你想要的任何格式。

【讨论】:

  • 我忘了SerializerMethodField。那肯定行得通。
【解决方案2】:

嗯,谢谢帮助,最后的代码是:

序列化器:

class UserPollsSerializer(ModelSerializer):

    answers = SerializerMethodField()

    # drf automatically finds this method by mask get_{field}
    def get_answers(self, obj):
        answers = self.context.get('answers_qs').filter(poll=obj)
        data = QuestionAnswerSerializer(answers, many=True).data
        return data

    class Meta:
        model = Poll
        fields = '__all__'

查看:

class PollMVS(ModelViewSet):
    serializer_class = PollSerializer
    permission_classes = [IsAdminUser]
    queryset = Poll.objects.all()

    # getting polls with answers by user_id
    @action(detail=False, methods=['get'])
    def user_polls(self, request):
        
        # here i get all polls with user's answers
        user_id = request.GET.get('user_id')
        polls_ids = QuestionAnswer.objects.values('poll').filter(user_id=user_id).distinct()
        u_polls = Poll.objects.filter(pk__in=polls_ids)
        
        # and here i pass them as a queryset and answers' queryset as context in a separate serializer
        serializer = UserPollsSerializer(u_polls, many=True, context={'answers_qs': QuestionAnswer.objects.filter(user_id=user_id)})
        return Response(serializer.data)

【讨论】:

    猜你喜欢
    • 2020-12-20
    • 2019-11-22
    • 2020-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-24
    • 2020-08-31
    相关资源
    最近更新 更多