Django REST Framework:序列化程序上下文如何工作?
Posted
技术标签:
【中文标题】Django REST Framework:序列化程序上下文如何工作?【英文标题】:Django REST Framework: how serializer context works? 【发布时间】:2016-09-13 12:04:45 【问题描述】:在 Django REST 框架中,提供额外的 args
/kwargs
以设置不是通过 request.data
设置的字段值,而是通过 url 参数或 cookie 中的值,这是 Django REST 框架中的一项非常标准的任务。例如,我需要在 POST 请求时将我的 Comment 模型的 user
字段设置为等于 request.user
。这些额外的参数称为上下文。
*** 上的几个问题(1、2)建议我覆盖我的ModelViewSet
的get_serializer_context()
方法。我做到了,但没有帮助。我试图理解,出了什么问题,并从源代码中发现我不明白这个上下文系统应该如何工作。 (也缺少有关此问题的文档)
谁能解释一下,序列化程序在哪里将上下文添加到正常的请求数据中?我找到了两个地方,它保存了上下文中的值。
-
serializer.save(),方法,将 kwargs 与经过验证的数据混合在一起,但通常在没有参数的情况下调用它(例如,ModelMixins)。
fields.
__new__()
,它缓存了 args 和 kwargs,但似乎没有人以后再阅读它们。
【问题讨论】:
【参考方案1】:设置字段的值不是通过 request.data 设置的,而是通过 url 参数或 cookie 中的值。例如,我需要在 POST 请求时将我的 Comment 模型的 user 字段设置为 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 的标准,但这不是重点。 :)
【讨论】:
【参考方案2】:每当您使用通用视图或视图集时,DRF(3.3.2) 都会将request
对象、view
对象和format
添加到序列化程序context
。您可以使用serializer.context
进行访问,比如在序列化程序中使用request.user
。
这是在调用get_serializer_class()
时添加的。在其中,它调用get_serializer_context()
方法,将所有这些参数添加到其上下文中。
DRF源代码供参考:
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
【讨论】:
我想了这么多,但后来会发生什么?我看不出,Serializer 在哪里利用这个上下文来用取自它的值填充字段。 在正常情况下,序列化程序不会使用上下文。如果我们想在序列化程序中访问request
对象,我们将使用self.context.get('request')
。此外,在任何序列化器字段的to_representation
方法中,我们可以使用self.context
变量访问context
。
(来自docs)包含context
的一个常见情况是,如果您使用包含超链接关系的序列化程序,这要求序列化程序有权访问当前请求,以便它可以正确生成完全限定的 URL。
@Rahul Gupta 你能帮我看看这个吗? ***.com/questions/62039305/…以上是关于Django REST Framework:序列化程序上下文如何工作?的主要内容,如果未能解决你的问题,请参考以下文章
python django-rest-framework 3.3.3 更新嵌套序列化程序
django-rest-framework、多表模型继承、ModelSerializers 和嵌套序列化器
Django.rest_framework:如何序列化一对多?
Django 序列化器与 rest_framework 序列化器