Django Rest Framework is a powerful and flexible toolkit for building web APIs. This post covers some basic usage of Django Rest Framework, including deploying an API for CRUD with Django models and serializers.
Installation
To install Django Rest Framework, we can use pip:
1
pip install djangorestframework
Then add rest_framework to INSTALLED_APPS in settings.py:
1 2 3 4
INSTALLED_APPS = [ ... 'rest_framework', ]
Models
Assume we have models for Note, Tag and Category. A note can have multiple tags and one category. The models are defined as follows:
By using api_view, we don’t need to define the content type of the request. The request.data will be parsed according to the content type of the request.
Serializers
To return the data in JSON format, we need to define serializers for models. We can use ModelSerializer to simplify the process. According to the DRF documentation, ModelSerializer is a shortcut to create a serializer class with fields that correspond to the Model fields.
The ModelSerializer class is the same as a regular Serializer class, except that:
It will automatically generate a set of fields for you, based on the model.
It will automatically generate validators for the serializer, such as unique_together validators.
It includes simple default implementations of .create() and .update().
Here are examples of serializers for Tag and Category:
1 2 3 4 5 6 7 8 9 10
classTagSerializer(serializers.ModelSerializer): classMeta: model = Tag fields = '__all__'# return all fields in the model
classCategorySerializer(serializers.ModelSerializer): classMeta: model = Category fields = '__all__'
These serializers are simple because we are using ModelSerializer. For the Note model, we need to customize the serializer to include the related fields. If we define the serializer as follows, the related fields will be returned as primary keys:
{ "note_id":1, "title":"Django Rest Framework basic usage", "content":"Django Rest Framework is a powerful and flexible toolkit for building web APIs. This post covers some basic usage of Django Rest Framework, including deploying an API for CRUD with Django models and serializers.", "created_at":"2024-03-16T23:13:08.000000Z", "updated_at":"2024-03-16T23:13:08.000000Z", "tags":[1,2,3], "category":1 }
To get the names of tags and category, we need to customize tags and category fields in the serializer:
{ "note_id":1, "title":"Django Rest Framework basic usage", "content":"Django Rest Framework is a powerful and flexible toolkit for building web APIs. This post covers some basic usage of Django Rest Framework, including deploying an API for CRUD with Django models and serializers.", "created_at":"2024-03-16T23:13:08.000000Z", "updated_at":"2024-03-16T23:13:08.000000Z", "tags":[ { "tag_id":1, "name":"Python" }, { "tag_id":2, "name":"Django" }, { "tag_id":3, "name":"Django Rest Framework" } ], "category":{ "category_id":1, "name":"Python" } }
PUT method
The PUT request for DRF is a little bit tricky. We need to override the update method in the serializer to handle the related fields. Here is an example of the update method in the NoteSerializer:
defupdate(self, instance, validated_data): # Get tags data and category data from validated_data # Return [] if tags is not in validated_data tags_data = validated_data.pop('tags', []) # Return None if category is not in validated_data category_data = validated_data.pop('category', None)
instance.tags.clear() for tag_data in tags_data: tag, created = Tag.objects.get_or_create(name=tag_data['name']) instance.tags.add(tag)
if category_data isnotNone: category, created = Category.objects.get_or_create(name=category_data['name']) instance.category = category instance.save()
return instance
The body of the PUT request should be in JSON format. Here is an example of the body:
1 2 3 4 5 6 7 8 9 10
{ "title":"Django Rest Framework basic usage", "content":"Django Rest Framework is a powerful and flexible toolkit for building web APIs. This post covers some basic usage of Django Rest Framework, including deploying an API for CRUD with Django models and serializers.", "tags":[ {"name":"Python"}, {"name":"Django"}, {"name":"Django Rest Framework"} ], "category":{"name":"Python"} }
POST method
The POST request is similar to the PUT request. We need to override the create method in the serializer to handle the related fields. Here is an example of the create method in the NoteSerializer:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
defcreate(self, validated_data): # Get tags data and category data from validated_data tags_data = validated_data.pop('tags') category_data = validated_data.pop('category')
note = Note.objects.create(**validated_data)
for tag_data in tags_data: tag, created = Tag.objects.get_or_create(name=tag_data['name']) note.tags.add(tag)
category, created = Category.objects.get_or_create(name=category_data['name']) note.category = category note.save()
return note
The body of the POST request should be in JSON format. Here is an example of the body:
1 2 3 4 5 6 7 8 9 10
{ "title":"Django Rest Framework basic usage", "content":"Django Rest Framework is a powerful and flexible toolkit for building web APIs. This post covers some basic usage of Django Rest Framework, including deploying an API for CRUD with Django models and serializers.", "tags":[ {"name":"Python"}, {"name":"Django"}, {"name":"Django Rest Framework"} ], "category":{"name":"Python"} }