Reputation: 638
When two serializer classes declare a SerializerMethodField with same name, like this:
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')
the code
serializer = APIProfileSerializer(instance=request.user, request=request)
return Response(data=serializer.data)
crashes with the following traceback:
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'
( my first question is: how to make traceback more readable in markdown? =) )
It's like request
hasn't been passed to serializer
however, this
serializer = ProfileSerializer(instance=request.user, request=request)
return Response(data=serializer.data)
and this
serializer = APIProfileSerializer(instance=request.user,request=request)
_data = serializer.data,
return Response(data=_data)
work fine...
Debugging show that BOTH APIProfileSerializer and ProfileSerializer are called, and the crash is caused by calling get_image
in ProfileSerializer
without passing request
to it
So, the question is: WTF?! I didn't call this serializer! I never even mentioned it in my views! How and for what reason is it being called?
I stick to the latter code piece to solve this problem, but there's got to be a better way! Any suggestions?
Upvotes: 0
Views: 1732
Reputation: 638
It appears that DRF's ImageField returns full URL if request
has been provided to serializer context, so there is no need for explicit URL construction. Clean and elegant (requires source studying though - official documentation does not mention this)
Upvotes: 0
Reputation: 638
I kinda solved it like this:
changed
if instance.image:
to
if instance.image and self.request:
so these under-the-hood get_image()
calls without a proper self.request
do not cause crashes anymore.
Still, it would be great to know why all of the above takes place
Upvotes: 1