Swagger not working with Django BaseSerializer object

I am using django-rest-swagger to document and test the API and it has been working very well so far, but the following error occurred:

AttributeError in / docs / api -docs / app PeriodSerializer object has no attribute 'get_fields'

'PeriodSerializer' inherits from serializers.BaseSerializer:

class PeriodSerializer(serializers.BaseSerializer):

    def to_representation(self, instance):
        return {
            'lower': instance.lower,
            'upper': instance.upper
        }

    def to_internal_value(self, data):
        data = json.loads(data)

        date_lower = self.date_from_str(data["lower"])
        date_upper = self.date_from_str(data["upper"])

        # some code omitted for brevity

        return DateTimeTZRange(lower=date_lower, upper=date_upper)


    @staticmethod
    def date_from_str(datestr):
        # code omitted for brevity

      

The code itself works fine, it just has a problem with django-rest-swagger. I use:

  • Python 3.4.0
  • Django 1.8.2
  • DRF 3.1.3
  • django-rest-swagger 0.3.2

Any help would be much appreciated.

+3


source to share


2 answers


Django Rest Framework BaseSerializer

has no feature get_fields

. You can see this in the source.

Short answer: use Serializer

, not BaseSerializer

. Your code will work the same and you don't have to worry about it. If for some reason you need to use BaseSerializer

and together django-rest-swagger

, you will have to implement it get_fields

yourself.

If you look at the implementation of get_fields in a higher level serializer (for example Serializer

), you can see that get_fields is defined like this:

def get_fields(self):
    """
    Returns a dictionary of {field_name: field_instance}.
    """
    # Every new serializer is created with a clone of the field instances.
    # This allows users to dynamically modify the fields on a serializer
    # instance without affecting every other serializer class.
    return copy.deepcopy(self._declared_fields)

      



Using BaseSerializer, you won't have access to self._declared_fields. You can see how this works in the linked source above, but the point is that it returns a dictionary of field type attributes.

Any instances Field

included as attributes in the class or on any of its superclasses will be included in the      _declared_fields

.

Hope this helps answer your question!

+2


source


Although late to the party, what works for me looks something like this:

@six.add_metaclass(serializers.SerializerMetaclass)
class PeriodSerializer(serializers.BaseSerializer):

    def get_fields(self):
        """
        Returns a dictionary of {field_name: field_instance}.
        """
        # Every new serializer is created with a clone of the field instances.
        # This allows users to dynamically modify the fields on a serializer
        # instance without affecting every other serializer class.
        return copy.deepcopy(self._declared_fields)

      



ie you need to decorate the class with the metaclass that _declared_field provides and then you can implement this method.

+1


source







All Articles