How to use Serializers in the Django Python web framework
======
Serialization transforms data into a format that can be stored or
transmitted and then reconstructs it for use. DRF has the best-known
serializers.
![Net catching 1s and 0s or data in the clouds][1]
Serialization is the process of transforming data into a format that can be stored or transmitted and then reconstructing it. It's used all the time when developing applications or storing data in databases, in memory, or converting it into files.
I recently helped two junior developers at [Labcodes][2]understand serializers, and I thought it would be good to share my approach with Opensource.com readers.
Suppose you're creating software for an e-commerce site and you have an Order that registers the purchase of a single product, by someone, at a price, on a date:
Now, imagine you want to store and retrieve order data from a key-value database. Luckily, its interface accepts and return dictionaries, so you need to convert your object into a dictionary:
```
def serialize_order(order):
return {
'product': order.product,
'customer': order.customer,
'price': order.price,
'date': order.date
}
```
And if you want to get some data from that database, you can get the dict data and turn that into your Order object:
```
def deserialize_order(order_data):
return Order(
product=order_data['product'],
customer=order_data['customer'],
price=order_data['price'],
date=order_data['date'],
)
```
This is pretty straightforward to do with simple data, but when you need to deal with complex objects made of complex attributes, this approach doesn't scale well. You also need to handle the validation of different types of fields, and that's a lot of work to do manually.
That's where frameworks' serializers are handy. They allow you to create serializers with little boilerplates that will work for your complex cases.
[Django][3] comes with a serialization module that allows you to "translate" Models into other formats:
It covers the most-used cases for web applications, such as JSON, YAML, and XML. But you can also use third-party serializers or create your own. You just need to register it in your settings.py file:
You can use the options parameters to define the behavior of your serializer. For example, if you want to define that you're going to work with nested serialization when dealing with `ForeignKeys` or you just want that data to return its primary keys, you can pass a `flat=True` param as an option and deal with that within your method:
```
class MyFormatSerializer:
def serializer(self, queryset, **options):
if options.get('flat', False):
# don't recursively serialize relationships
# recursively serialize relationships
```
One way to use Django serialization is with the `loaddata` and `dumpdata` management commands.
### DRF serializers
In the Django community, the [Django REST framework][4](DRF) offers the best-known serializers. Although you can use Django's serializers to build the JSON you'llrespond to in your API, the one from the REST framework comes with nice features that help you deal with and easily validate complex data.
In the Order example, you could create a serializer like this:
After that, you can create or update instances by calling `is_valid()` to validate the data and `save()` to create or update an instance:
```
serializer = OrderSerializer(**data)
## to validate data, mandatory before calling save
serializer.is_valid()
serializer.save()
```
### Model serializers
When serializing data, you often need to do it from a database, therefore, from your models. A ModelSerializer, like a ModelForm, provides an API to create serializers from your models. Suppose you have an Order model:
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = '__all__'
```
Django automatically includes all model fields in the serializer and creates the `create` and `update` methods.
### Using serializers in class-based views (CBVs)
Like Forms with Django's CBVs, serializers integrate well with DRFs. You can set the `serializer_class` attribute so that the serializer will be available to the view:
```
from rest_framework import generics
class OrderListCreateAPIView(generics.ListCreateAPIView):
queryset = Order.objects.all()
serializer_class = OrderSerializer
```
You can also define the `get_serializer_class()` method:
```
from rest_framework import generics
class OrderListCreateAPIView(generics.ListCreateAPIView):
queryset = Order.objects.all()
def get_serializer_class(self):
if is_free_order():
return FreeOrderSerializer
return OrderSerializer
```
There are other methods in CBVs that interact with serializers. For example, [get_serializer()][5] returns an already-instantiated serializer, while [get_serializer_context()][6] returns the arguments you'll pass to the serializer when creating its instance. For views that create or update data, there are `create` and `update` that validate the data with the `is_valid` method to be saved, and [perform_create][7] and [perform_update][8] that call the serializer's save method.
### Learn more
For other resources, see my friend André Ericson's [Classy Django RESTFramework][9] website. It is a [Classy Class-Based Views][10] REST Framework version that gives you an in-depth inspection of the classes that compose DRF. Of course, the official [documentation][11] is an awesome resource.
[1]: https://opensource.com/sites/default/files/styles/image-full-size/public/lead-images/data_analytics_cloud.png?itok=eE4uIoaB (Net catching 1s and 0s or data in the clouds)