How to use different serializers with DjangoRestFramework
Imagine to have a viewset and you want to parametrize the output, using different serializers.
class Person(models.Model):
title = models.CharField(...)
last_name = models.CharField(...)
first_name = models.CharField(...)
mail = models.EmailField(...)
address = models.CharField(...)
birthday = models.DateField()
class PersonSerializer(HouseSerializer):
full_name = serializers.SerializerMethodField()
class Meta:
model = House
fields = ('title', 'last_name', 'first_name', 'mail', 'full_name')
def get_full_name(self, obj):
return "{0.last_name}, {1.first_name}".format(obj)
class PersonView(DynamicSerializerMixin, generics.ListAPIView):
queryset = House.objects.all()
serializer_class = HouseSerializer
it is easy to build a "serializer factory" to build on the fly
cache = {}
def serializer_factory(model, base=ModelSerializer, fields=None, exclude=None):
attrs = {'model': model}
if fields is not None:
attrs['fields'] = fields
if exclude is not None:
attrs['exclude'] = exclude
parent = (object,)
if hasattr(base, 'Meta'):
parent = (base.Meta, object)
Meta = type(str('Meta'), parent, attrs)
if model:
class_name = model.__name__ + 'Serializer'
else:
class_name = 'Serializer'
return type(base)(class_name, (base,), {'Meta': Meta, })
class DynamicSerializerMixin(object):
serializers_fieldsets = {'std': None}
serializer_class = ModelSerializer
def get_serializer_class(self):
ser = self.request.QUERY_PARAMS.get('serializer', 'std')
if ser not in cache:
fields = self.serializers_fieldsets.get(ser, 'std')
cache[ser] = serializer_factory(self.model,
self.serializer_class,
fields=fields)
return cache[ser]
adopt it:
class PersonView(DynamicSerializerMixin, generics.ListAPIView):
queryset = Person.objects.all()
serializer_class = PersonSerializer
serializers_fieldsets = {'std': PersonSerializer,
'simple': ('first_name', 'last_name')
}
invoke it:
?serializer=std
?serializer=simpleA