首页 文章

Django REST框架:序列化程序上下文如何工作?

提问于
浏览
10

Django REST Framework中的一个非常标准的任务是为序列化程序提供额外的 args / kwargs 来设置不是通过 request.data 设置的字段值,而是通过url参数或cookie中的值 . 例如,我需要在POST请求时将我的Comment模型的 user 字段设置为 request.user . 这些额外的参数称为上下文 .

StackOverflow上的几个问题(12)建议我覆盖 ModelViewSetget_serializer_context() 方法 . 我做了,它没有错误,并且发现我从源代码中无法理解,这个上下文系统应该如何工作 . (关于此事的文件也遗失了)

谁能解释一下,序列化程序在正常的请求数据中添加了上下文?我找到了两个地方,它从上下文中保存了值 .

  • serializer.save(),方法,它将kwargs与验证数据混合,但通常不带参数调用(例如,通过ModelMixins) .

  • fields.new(),它缓存args和kwargs,但似乎以后没有人读过它们 .

2 回答

  • 0

    无论何时使用通用视图或视图集,DRF(3.3.2)都会将 request object, view object和 format 添加到序列化程序 context . 您可以使用 serializer.context 进行访问,让我们在序列化程序中说 request.user .

    调用 get_serializer_class() 时会添加此项 . 在其中,它调用 get_serializer_context() 方法,其中所有这些参数都添加到其上下文中 .

    DRF source code for reference:

    class GenericAPIView(views.APIView):
        """
        Base class for all other generic views.
        """
    
        def get_serializer(self, *args, **kwargs):
            """
            Return the serializer instance that should be used for validating and
            deserializing input, and for serializing output.
            """
            serializer_class = self.get_serializer_class()
            kwargs['context'] = self.get_serializer_context()
            return serializer_class(*args, **kwargs)    
    
        def get_serializer_context(self):
            """
            Extra context provided to the serializer class.
            """
            return {
                'request': self.request,
                'format': self.format_kwarg,
                'view': self
            }
    
  • 10

    设置不是通过request.data设置的字段值,而是通过url参数或cookie中的值设置 . 例如,我需要在POST请求中将我的Comment模型的用户字段设置为等于request.user .

    这就是我在ModelViewSet中处理这两种情况的方法:

    def perform_create(self, serializer):
    
        # Get article id from url e.g. http://myhost/article/1/comments/
        # obviously assumes urls.py is setup right etc etc
        article_pk = self.kwargs['article_pk']
        article = get_object_or_404(Article.objects.all(), pk=article_pk)
    
        # Get user from request
        serializer.save(author=self.request.user, article=article)
    

    不幸的是,嵌套对象不是DRF的标准对象,但除此之外 . :)

相关问题