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.
source to share
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!
source to share
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.
source to share