HaystackSerializer (SerializerMethodField) does not pass instance
bpx279 opened this issue · 7 comments
Prior to 1.8.5, I had no issue with my serializers, but upon updating, my Serializer started failing with a SerializerMethodField failing with get_custom_field() missing 1 required positional argument: 'instance'.
I did not have time to investigate further. For now, I only reverted to 1.8.4.
Ok, can you please paste your traceback?
As of commit 711402b we can see in drf_haystack.serializers.HaystackSerializer#to_representation
:
ret[field] = value_method()
does not pass instance
into value_method
so we get get_last_update() takes exactly 1 argument (0 given)
for SerializerMethodField
Example serializer:
class GameSerializer(HaystackSerializer):
last_update = fields.SerializerMethodField()
@staticmethod
def get_last_update(obj):
return {
"price": obj.formatted_price,
"price_old": obj.formatted_old_price,
}
I have the same issue. Here's the traceback...
TypeError: get_content_type() missing 1 required positional argument: 'instance'
File "django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "rest_framework/viewsets.py", line 116, in view
return self.dispatch(request, *args, **kwargs)
File "rest_framework/views.py", line 495, in dispatch
response = self.handle_exception(exc)
File "rest_framework/views.py", line 452, in handle_exception
response = exception_handler(exc, context)
File "rest_framework/views.py", line 492, in dispatch
response = handler(request, *args, **kwargs)
File "rest_framework/mixins.py", line 45, in list
return self.get_paginated_response(serializer.data)
File "rest_framework/serializers.py", line 768, in data
ret = super(ListSerializer, self).data
File "rest_framework/serializers.py", line 262, in data
self._data = self.to_representation(self.instance)
File "api/tags/serializers/tag_serializer.py", line 110, in to_representation
data = super().to_representation(data)
File "rest_framework/serializers.py", line 686, in to_representation
self.child.to_representation(item) for item in iterable
File "rest_framework/serializers.py", line 686, in <listcomp>
self.child.to_representation(item) for item in iterable
File "drf_haystack/serializers.py", line 233, in to_representation
ret[field] = value_method()
And here's what the serializer looks like.
class TagSerializer(HaystackSerializer):
content_type = serializers.SerializerMethodField()
# ...
@staticmethod
def get_content_type(instance):
return # ...
From the DRF documentation:
The serializer method referred to by the method_name argument should accept a single argument (in addition to self), which is the object being serialized.
Right now, the serializer methods do not get that object.
This issue was introduced in #135 (#99). I think #135 needs to be reverted, because this is not how you use a serializer method in DRF.
DRF provides serializers.SerializerMethodField
exactly for this purpose. With the solution in this PR we're just re-inventing stuff. Look at the code in SerializerMethodField.bind()
, it does exactly the same.
@rhblind Did you forget to push a new release with the fix? Latest I can find in PyPI is still 1.8.5 from May 21st.
Hey guys!
Yeah, sorry I totally forgot about it. I've started a new position in a new company so I've been quite busy getting into that. I'll see I can push a new release during the weekend.