Django REST框架:从视图传递额外的上下文数据到序列化器

huangapple go评论65阅读模式
英文:

Django REST framework: passing additional contextual data from view to serializer

问题

I have a Django REST framework view (generics.GenericAPIView). In it, I want to pass contextual data (the original request received by the view) to a serializer.

As per https://stackoverflow.com/questions/52188500/serializer-including-extra-context-in-django-rest-framework-3-not-working, I've overridden the get_serializer_context() method inherited from Rest Framework's GenericAPIView.

My view looks like this:

class MyView(GenericAPIView):
    def get_serializer_context(self):
        context = super().get_serializer_context()
        context.update({"original_request": self.request})
        return context

    def put(self, request, *args, **kwargs):
        my_object = ... get object from the database ...

        serializer = MySerializer(my_instance=my_object, validated_data=request.data)

        if serializer.is_valid():
            logger.warning("MyView/put() - request: " + str(request))
            .... other stuff ...

My serializer:

class MySerializer():
    def update(self, my_instance, validated_data):
        logger.warning("MySerializer/update() - context: " + str(self.context))
        ... other stuff ...

My view's logs show that the request details are present:

MyView/put() - request: <rest_framework.request.Request: PUT '<URL>'>

... but they are not passed to the serializer:

MySerializer/update() - context: {}

I'm suspecting that it's because the self.request value in get_serializer_context() is not populated or is not the same as the one supplied in the view's put() method.

I've also tried including the context data directly during the instantiation of the serializer, as per https://www.django-rest-framework.org/api-guide/serializers/#including-extra-context but that didn't work either - again, the contextual data was not passed from the view to the serializer.

How can I supply the additional contextual data to the serializer for individual requests via generics.GenericAPIView, please?

Many thanks for any information.

英文:

I have a Django REST framework view (generics.GenericAPIView). In it, I want to pass contextual data (the original request received by the view) to a serializer.

As per https://stackoverflow.com/questions/52188500/serializer-including-extra-context-in-django-rest-framework-3-not-working, I've overridden the get_serializer_context() method inherited from Rest Framework's GenericAPIView.

My view looks like this:

class MyView(GenericAPIView):
    def get_serializer_context(self):
        context = super().get_serializer_context()
        context.update({&quot;original_request&quot;: self.request})
        return context

    def put(self, request, *args, **kwargs):
        my_object = ... get object from database ...

        serializer = MySerializer(my_instance=my_object, validated_data=request.data)

        if serializer.is_valid():
            logger.warning(&quot;MyView/put() - request: &quot; + str(request))
            .... other stuff ...

My serializer:

class MySerializer():
    def update(self, my_instance, validated_data):
        logger.warning(&quot;MySerializer/update() - context: &quot; + str(self.context))
        ... other stuff ...

My view's logs shows that the request details are present:

MyView/put() - request: &lt;rest_framework.request.Request: PUT &#39;&lt;URL&gt;&#39;&gt;

... but they are not passed to the serializer:

MySerializer/update() - context: {}

I'm suspecting that it's because the self.request value in get_serializer_context() is not populated or is not the same as the one supplied in the view's put() method.

I've also tried including the context data directly during the instantiation of the serializer, as per https://www.django-rest-framework.org/api-guide/serializers/#including-extra-context but that didn't work either - again, the contextual data was not passed from the view to the serializer.

How can I supply the additional contextual data to the serializer for individual requests via generics.GenericAPIView, please?

Many thanks for any information.

答案1

得分: 2

你正在直接调用序列化器类,并在这种情况下需要手动传递context

但我会考虑使用get_serializer(...)方法来获取序列化器实例。

英文:

You are calling the serializer class directly and in that situation you have to pass the context manually

<pre><code>
class MyView(GenericAPIView):
def get_serializer_context(self):
context = super().get_serializer_context()
context.update({"original_request": self.request})
return context

def put(self, request, *args, **kwargs):
    instance = self.get_object()
    &lt;b&gt;serializer = MySerializer(
        instance,
        data=request.data,
        partial=False,
        context=self.get_serializer_context()
    )&lt;/b&gt;
    serializer.is_valid(raise_exception=True)
    serializer.save()
    return Response(serializer.data)

</code></pre>

But, I would consider using the get_serializer(...) method to get the serializer instance

<pre><code>
class MyView(GenericAPIView):
def get_serializer_context(self):
context = super().get_serializer_context()
context.update({"original_request": self.request})
return context

def put(self, request, *args, **kwargs):
    instance = self.get_object()
    &lt;b&gt;serializer = self.get_serializer(instance, data=request.data, partial=False)&lt;/b&gt;
    serializer.is_valid(raise_exception=True)
    serializer.save()
    return Response(serializer.data)

</code></pre>

huangapple
  • 本文由 发表于 2023年4月20日 07:03:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76059423.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定