django rest framework SerializerMethodField离奇的行为

django rest framework SerializerMethodField bizarre behaviour

当两个序列化程序类声明具有相同名称的SerializerMethodField时,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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')

代码

1
2
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'

(我的第一个问题是:如何使回溯在标记中更具可读性?=)

就像EDOCX1[0]没有传递给序列化程序

然而,这

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

还有这个

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

工作正常…

调试表明,调用了apiProfileSerializer和profileSerializer,导致崩溃的原因是在ProfileSerializer中调用get_image而没有将request传递给它。

所以,问题是:世贸组织?!我没有调用这个序列化程序!我从来没有在我的观点中提到过!它是如何被称为什么原因的?

我坚持使用后一段代码来解决这个问题,但必须有更好的方法!有什么建议吗?


我有点像这样解决了它:

改变

1
if instance.image:

1
if instance.image and self.request:

因此,这些在引擎盖下的get_image()呼叫如果没有合适的self.request就不会再导致崩溃。

尽管如此,知道为什么会发生上述所有事情还是很好的。


如果request已提供给序列化程序上下文,那么drf的imagefield似乎返回完整的url,因此不需要显式的url构造。干净优雅(但需要来源研究-官方文件没有提到这一点)