Django的REST框架SerializerMethodField怪异行为

Django的REST框架SerializerMethodField怪异行为

问题描述:

当两个串行类声明具有相同名称的SerializerMethodField,像这样:Django的REST框架SerializerMethodField怪异行为

class APIProfileSerializer(serializers.ModelSerializer): 
    def __init__(self, *args, **kwargs): 

     super(APIProfileSerializer, self).__init__(*args, **kwargs) 
     self.request = request 

    def get_image(self, instance): 

     if instance.image: 
      return self.request.build_absolute_uri(location=instance.image.url) 
     return None 

    image = serializers.SerializerMethodField() 

    # other ProfileSerializer fields 

    class Meta: 
     model = User 
     fields = ('image') 



class ProfileSerializer(serializers.ModelSerializer): 
    def __init__(self, *args, **kwargs): 

     super(ProfileSerializer, self).__init__(*args, **kwargs) 
     self.request = request 

    def get_image(self, instance): 

     if instance.image: 
      return self.request.build_absolute_uri(location=instance.image.url) 
     return None 

    image = serializers.SerializerMethodField() 

    # other ProfileSerializer fields 

    class Meta: 
     model = User 
     fields = ('image') 

代码

serializer = APIProfileSerializer(instance=request.user, request=request) 
return Response(data=serializer.data) 

崩溃,并显示以下追踪:

Traceback (most recent call last): File "/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/django/core/handlers/base.py", line 174, in get_response response = self.process_exception_by_middleware(e, request) File "/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/django/core/handlers/base.py", line 172, in get_response response = response.render() File "/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/django/template/response.py", line 160, in render self.content = self.rendered_content File "/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/response.py", line 71, in rendered_content ret = renderer.render(self.data, media_type, context) File "/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/renderers.py", line 675, in render context = self.get_context(data, accepted_media_type, renderer_context) File "/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/renderers.py", line 618, in get_context raw_data_put_form = self.get_raw_data_form(data, view, 'PUT', request) File "/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/renderers.py", line 540, in get_raw_data_form content = renderer.render(serializer.data, accepted, context) File "/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/serializers.py", line 503, in data ret = super(Serializer, self).data File "/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/serializers.py", line 239, in data self._data = self.to_representation(self.instance) File "/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/serializers.py", line 472, in to_representation ret[field.field_name] = field.to_representation(attribute) File "/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/fields.py", line 1645, in to_representation return method(value) File "/home/ubuntu/vhosts/superhq_backend/account/serializers.py", line 32, in get_image return self.request.build_absolute_uri(location=instance.image.url) AttributeError: 'NoneType' object has no attribute 'build_absolute_uri'

(我的第一个问题是:如何使痕迹更容易在减价中读取? =))

这就像request尚未传递到序列化器

然而,这

serializer = ProfileSerializer(instance=request.user, request=request) 
return Response(data=serializer.data) 

serializer = APIProfileSerializer(instance=request.user,request=request) 
_data = serializer.data, 
return Response(data=_data) 

做工精细...

调试显示调用了APIProfileSerializer和ProfileSerializer,并且致命get_imageProfileSerializer没有通过request

因此,问题是:WTF ?!我没有叫这个序列化器!我从来没有在我的意见中提及它!如何和为什么被称为?

我坚持用后面的代码来解决这个问题,但是这里有一个更好的方法!有什么建议么?

看来,如果request已经提供给串行背景DRF的ImageField的返回完整的URL,所以没有必要明确的URL结构。清洁和优雅(需要来源学习 - 虽然官方文档没有提到这一点)

我还挺解决这样的:

改变

if instance.image: 

if instance.image and self.request: 

所以这些在引擎罩get_image()调用没有正确的self.request不会造成死机了。

不过,这将是巨大的,知道为什么所有的上述发生地