django rest framework SerializerMethodField 奇怪的行为
Posted
技术标签:
【中文标题】django rest framework SerializerMethodField 奇怪的行为【英文标题】:django rest framework SerializerMethodField bizarre behaviour 【发布时间】:2016-05-23 18:56:29 【问题描述】:当两个序列化器类声明一个同名的 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(最近一次调用最后一次): 文件“/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/django/core/handlers/base.py”,第 174 行,在 get_response response = self.process_exception_by_middleware(e, request) 文件“/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/django/core/handlers/base.py”,第 172 行,在 get_response 响应 = response.render() 文件“/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/django/template/response.py”,第 160 行,在渲染中 self.content = self.rendered_content 文件“/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/response.py”,第 71 行,在 render_content 中 ret = renderer.render(self.data, media_type, context) 文件“/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/renderers.py”,第 675 行,在渲染中 上下文 = self.get_context(数据,accepted_media_type,renderer_context) 文件“/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/renderers.py”,第 618 行,在 get_context raw_data_put_form = self.get_raw_data_form(数据,视图,'PUT',请求) 文件“/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/renderers.py”,第 540 行,在 get_raw_data_form content = renderer.render(serializer.data, 接受, 上下文) 文件“/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/serializers.py”,第 503 行,数据 ret = super(Serializer, self).data 文件“/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/serializers.py”,第 239 行,数据 self._data = self.to_representation(self.instance) to_representation 中的文件“/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/serializers.py”,第 472 行 ret[field.field_name] = field.to_representation(属性) 文件“/home/ubuntu/venv/superhq_rest/lib/python3.4/site-packages/rest_framework/fields.py”,第 1645 行,在 to_representation 返回方法(值) 文件“/home/ubuntu/vhosts/superhq_backend/account/serializers.py”,第 32 行,在 get_image 返回 self.request.build_absolute_uri(location=instance.image.url) AttributeError: 'NoneType' 对象没有属性 'build_absolute_uri'
(我的第一个问题是:如何让traceback在markdown中更具可读性?=))
就像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都被调用,崩溃是因为在ProfileSerializer
中调用get_image
而没有传递request
给它
所以,问题是:WTF?!我没有调用这个序列化程序!我什至从未在我的观点中提及它!它是如何以及出于什么原因被调用的?
我坚持使用后一个代码片段来解决这个问题,但一定有更好的方法!有什么建议吗?
【问题讨论】:
【参考方案1】:我是这样解决的:
改变了
if instance.image:
到
if instance.image and self.request:
因此,这些没有正确 self.request
的底层 get_image()
调用不会再导致崩溃。
不过,很高兴知道为什么会发生上述所有情况
【讨论】:
【参考方案2】:如果request
已提供给序列化程序上下文,DRF 的 ImageField 似乎会返回完整的 URL,因此不需要显式的 URL 构造。干净优雅(需要研究源代码 - 官方文档没有提到这一点)
【讨论】:
以上是关于django rest framework SerializerMethodField 奇怪的行为的主要内容,如果未能解决你的问题,请参考以下文章
在 Django REST Framework 的 CreateAPIView 中的 create() 之后返回不同的序列化程序
17-Django-Django REST framework-REST framework及RESTful简介
Django-rest-framework 和 django-rest-framework-jwt APIViews and validation Authorization headers
Django Rest Framework 和 django Rest Framework simplejwt 两因素身份验证