rhblind/drf-haystack

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.

mizi commented

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.

Agreed with @mizi. This functionality is already supported by stock DRF and no need to duplicate it here. This has been fixed in #143 and are merged to master branch. Will push a release within a few days.

@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.