Member-only story
Django Rest Framework — Writing Serializers that Differ From Your Internal Data Model
No matter how hard we try to get our data model correct (and even if we’ve done so!) sometimes by the time we need to use it, either for a public-facing API or an internal one, we need things to look a little different. Django Rest Framework(DRF) has some useful tools for allowing us to build serializers based on our models that differ somewhat from how we’ve defined things internally.
For our example, we’ll say we have a data model that looks, in part, like this:
class Item(models.Model):
name = models.CharField(max_length=255)
...class Offer(models.Model):
item = models.ForeignKey(Item)
...class Purchase(models.Model):
offer = models.ForeignKey(Offer)
...
If we want to allow users to access Item
s via the API, we may add an ItemSerializer
that leverages DRF’s ModelSerializer functionality, and looks like this, to start:
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = Item
fields = ('name',)
Below are just two of the most common ways I’ve seen folks override their external data models to differ from internal ones. Other things you’re trying to accomplish that you’re not sure how to do? Feel free to reach out and I’ll add to this post! ✉️
Calculated or Generated Data
Not all of the information we present is stored in the database, or should be. Sometimes we need to calculate or generate a piece of information at the time the data is requested. One example of this would be generating a login_token
for a User
when that record is accessed. For our example, we’ll include the number of times an item was purchased by adding a purchase_count
to our ItemSerializer
. The SerializerMethodField is perfect for this.
A SerializerMethodField
is a read-only field that allows you to define a method that is evaluated when the resource is accessed, and the return data used as the value for this field. The method should be given the name get_<field_name>
to be referenced automatically. Once we’ve added this field, our serializer will look like this: