Composing Serializers With DRF
a readDjango Rest Framework provides a fast way to build APIs, expressing them as a set of serializers and views. I recently ran into a case where I wanted user-specific data to be included when a user is authenticated, but default to the generic serializer in all other cases.
/api/v1/items/2 (anonymous)
|
|
/api/v1/items/2 (authenticated)
|
|
This lead to two separate but similar serializers, only differing with the inclusion of the favorited
field. In
Python composition inherits fields from both parents but patching DRF’s Meta class is a little difficult since it can’t
reach into the parent class to fetch the (potentially inherited) list of fields. But, fear not, as we’re about to do
some meta-programming (pun intended). In short, we can use a decorator to generate a new class with the correct
information in the Meta class, saving some headache and keeping things nice and DRY in the process.
For reference, here are our old serializers:
serializers.py
|
|
Even in this simple example, there is a good deal of repetition. By composing them together we can condense the the last three serializers down considerably:
serializers.py (new)
|
|
The decorator works by combining the Meta class for each of the parent serializers as well as adding the fields defined
in the Meta for the child class. Additionally, all the behaviour from normal python inheritance applies such as
the function defined in the ItemPriceSerializer
. Now, any changes to the parents will be correctly reflected in the
child. Simple.