Creating views and serializers — Django Rest Framework

Build a Product Review Backend with DRF — Part 3

Emre Cevik
Python | Django & Rest
7 min readOct 15, 2020

--

Previous parts we used Django core. In this section django rest framework is coming. We’ll learn basic knowledge about serializers, views and url patterns.

We need to add rest_framework to the INSTALLED_APPS parameter in settings.py file.

Serializers

To make our objects available through the API, we need to perform a serialization. A serializer is a framework that allows complex data such as querysets and model instances to be converted to native Python data types. Then, these can then be easily rendered into JSON or other content types. The reverse process is called deserialization. The serializers work in a way similar to Django’s Form classes.

The ModelSerializer class provides a shortcut that lets you automatically create a Serializer class with fields that correspond to the Model fields and it will automatically generate validators for the serializer.

Let’s create reviews/serializers.py file and type the following lines of code:

Specifying which fields to include

You can also set the fields attribute to the special value __all__ to indicate that all fields in the model should be used.

fields = '__all__' 

You can set the exclude attribute to a list of fields to be excluded from the serializer.

exclude = ['category'] # pk and name to be serialized

You can specify read only fields. Model fields which have editable=False set, and AutoField fields will be set to read-only by default.

read_only_fields = ['name']

There is also a shortcut allowing you to specify arbitrary additional keyword arguments on fields, using the extra_kwargs option.

extra_kwargs = {'name': {'read_only': True}}

Validation

With Django the validation is performed partially on the form, and partially on the model instance. With Django Rest Framework the validation is performed entirely on the serializer class. When you’re using ModelSerializer all of this is handled automatically for you. If you want to drop down to using Serializer classes instead, then you need to define the validation rules explicitly.

Field Level Validation : You can specify custom field-level validation by adding validate_<field_name> methods to your Serializer subclass.

Object Level Validation : To do any other validation that requires access to multiple fields, add a method called validate() to your Serializer subclass.

Overriding Serializer Methods : If we want to be able to return complete object instances based on the validated data we need to implement one or both of the create() and update() methods to our Serializer subclass.

Including extra context : You can provide arbitrary additional context by passing a context argument when instantiating the serializer. The context dictionary can be used within any serializer field logic by accessing the self.context attribute.

serializer = ProductSerializer(account, context={‘request’: request})

Nested relationships : As opposed to previously discussed references to another entity, the referred entity can instead also be embedded or nested in the representation of the object that refers to it. Such nested relationships can be expressed by using serializers as fields. If the field is used to represent a to-many relationship, you should add the many=True flag to the serializer field.

SerializerMethodField: This is a read-only field. It gets its value by calling a method on the serializer class it is attached to. It can be used to add any sort of data to the serialized representation of your object.

Now we can use the serializers to write views.

Views

Django Rest-Framework supports two different types of views.

1 — Function Based Views
2 — Class Based Views (Generic Views, ViewSets)

We’ll use ViewSets (Class Based Views).

ViewSets works exactly same as Generic Views. The only difference is using ViewSet you don’t have to create separate views for getting list of objects and detail of one object. We do not configure the urls with ViewSets. Routers generates urls for ViewSets automatically and binds methods for different request method types.

GenericViewSet
The GenericViewSet class does not provide any actions/methods by default such as GET, POST, PUT but does include the base set of generic view behavior, such as the get_object and get_queryset methods.

ReadOnlyModelViewSet
A viewset that provides default list() and retrieve() actions. It accepts only accepts the request method type GET.

ModelViewSet
A viewset that provides default create(), retrieve(), update(), partial_update(), destroy() and list() actions.

|--------------|---------|------------------|----------------------|
| ENDPOINT | METHOD | ACTION | DESCRIPTION |
|--------------|---------|------------------|----------------------|
| products/ | GET | list() | Get all products |
| products/ | POST | create() | Create new product |
| products/:pk | GET | retrieve() | Get product details | | products/:pk | PUT | update() | Update product |
| products/:pk | PATCH | partial_update() | Part. update product |
| products/:pk | DELETE | delete() | Delete product |
|--------------|---------|------------------|----------------------|

For adding ViewSet open the file reviews/views.py and type the following lines of code:

You’ll need yo set queryset and serializer_class attributes or override get_queryset() and get_serializer_class() methods.

ProductViewSet extended from ReadOnlyModelViewSet. Our viewset provides only get actions.

|--------------|---------|------------------|----------------------|
| ENDPOINT | METHOD | ACTION | DESCRIPTION |
|--------------|---------|------------------|----------------------|
| products/ | GET | list() | Get all products |
| products/:pk | GET | retrieve() | Get product details |
|--------------|---------|------------------|----------------------|

Marking extra actions for routing

If you have ad-hoc methods that should be routable, you can mark them as such with the @action decorator. Like regular actions, extra actions may be intended for either a single object, or an entire collection. To indicate this, set the detail argument to True or False. The router will configure its URL patterns accordingly.

|-----------------------------|---------|----------------------|
| ENDPOINT | METHOD | ACTION |
|-----------------------------|---------|----------------------|
| products/ | GET | list() |
| products/:pk | GET | retrieve() |
| products/get_list | GET | get_list() |
| products/get_product/:pk | GET | get_product() |
| products/delete_product/:pk | DELETE | delete_product() |
| products/delete_product/:pk | POST | delete_product() |
|-----------------------------|---------|----------------------|

The final step is to create a basic routing for the API and connect the ViewSets. Open the file medium/urls.py and type the following lines of code:

Browsable API

API may stand for Application Programming Interface, but humans have to be able to read the APIs, too; someone has to do the programming. Django REST Framework supports generating human-friendly HTML output for each resource when the HTML format is requested. These pages allow for easy browsing of resources, as well as forms for submitting data to the resources using POST, PUT, and DELETE.

Runserver and check product list and product detail endpoints. You should see similar pages.

Product List
http://127.0.0.1:8000/product/
Product Detail
http://127.0.0.1:8000/product/1/

Detailed descriptions for each of Django REST Framework’s class-based views and serializers you can check http://www.cdrf.co/

Now we need to add some data to the database for using Company, ProductSize, ProductSite and Comment models. You can use shell or admin site for this.

CompanyName : TrueCar
Url : http://www.truecar.com
Name : Edmunds
Url : http://www.edmunds.com
Name : CarMax
Url : http://www.carmax.com
ProductSizeName : 10- feet
Name : 10-12 feet
Name : 13-15 feet
Name : 15-17 feet
Name : 18+ feet
ProductSiteName : Mercedes-Benz CLA (2017)
Product :
Mercedes-Benz CLA
Company :
TrueCar
Product Size :
13-15 feet
Price :
20000
Url :
http://www.truecar.com/1.html
Name : 2014 - Mercedes-Benz E-Class
Product :
Mercedes-Benz E-Class
Company :
Edmunds
Product Size :
13-15 feet
Price :
20000
Url :
http://www.edmunds.com/2.html
Name : Mercedes-Benz E-Class - New 2020
Product :
Mercedes-Benz E-Class
Company :
CarMax
Product Size :
15-17 feet
Price :
35000
Url :
http://www.carmax.com/1.html
Name : Audi A1 (2019)
Product :
Audi A1
Company :
TrueCar
Product Size :
10-12 feet
Price :
35000
Url :
http://www.truecar.com/2.html
Name : BMW 7 Series - 2019
Product :
BMW 7 Series
Company :
CarMax
Product Size :
15-17 feet
Price :
30000
Url :
http://www.carmax.com/2.html
CommentTitle : title 1
Content :
content 1
Product :
Mercedes-Benz E-Class
User :
admin
Title : title 2
Content :
content 2
Product :
Mercedes-Benz E-Class
User :
admin
Title : title 3
Content :
content 3
Product :
Mercedes-Benz E-Class
User :
admin
Title : title 4
Content :
content 4
Product :
BMW 7 Series
User :
admin

You can download part 3 files from

In the next part, we’ll create product backend.

If you want to learn more about Django, do check out the documentation, django rest framework website and make sure to check out part of this series!

--

--