Now we will add the base User endpoints defined by the Quickstart guide at the Django REST Framework website. These resources will allow Admin users to make changes to the User model. We will make more additions later (token authentication anyone?), but it is important to cover/show the ease of DRF first!

7. Serializers

We must first create some serializers. Serializers are defined by DRF as:

Serializers allow complex data such as querysets and model instances to be converted to native Python datatypes that can then be easily rendered into JSON , XML or other content types. Serializers also provide deserialization, allowing parsed data to be converted back into complex types, after first validating the incoming data. The serializers in REST framework work very similarly to Django’s Form and ModelForm classes. We provide a Serializer class which gives you a powerful, generic way to control the output of your responses, as well as a ModelSerializer class which provides a useful shortcut for creating serializers that deal with model instances and querysets.

With that we can break serializers down to two main uses:

Get model data from the database in JSON Use them like forms to validate data and create instances of a model

There are different types of serializers, but we will focus our efforts today on HyperlinkedModelSerializers. To understand them, we must first look at ModelSerializers:

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() .

HyperlinkedModelSerializers build on top of ModelSerializers by using a URL instead of primary key values to define relations. Thus when getting data back from a serializer, you will get a field url instead of pk .

All of those things can manually be done, however we should opt to use HyperlinkedModelSerializer 9 times out of 10 when dealing with Model manipulation. In more advanced cases, we may need to write an entire Serializer by hand.

Full documentation on DRF Serializers can be found here.

Now we will create our Serializer for the User model. First create serializers.py :

# Command

touch project/api/serializers.py

Inside of the file project/api/serializers.py we will add the class UserSerializer :

from django.contrib.auth.models import User

from rest_framework import serializers class UserSerializer(serializers.HyperlinkedModelSerializer):

class Meta:

model = User

fields = ('url', 'username', 'email', 'groups')

We have imported the User model and created a HyperlinkedModelSerializer that will get us the data associated with the model, as well as the URL to the instance.

That URL would go to that model’s User Detail page. When that User is represented as a foreign key to other objects, the URL will be displayed instead of a simple PK.

8. Views

We will now create a View that allows a URL to get data from a serializer and return that data to a user/endpoint. To get there we need to understand Views, Class-Based Views, and ViewSets.

8–1. Views

First, one must understand what a View is. As defined by Django:

A view function, or view for short, is simply a Python function that takes a Web request and returns a Web response.

Well it’s a good thing we know all about HTTP requests and responses now!

Views “handle linking the URLs, HTTP method dispatching (GET, POST, etc)”, among other things.

8–2. Class-Based Views

Most beginner Django developers end up writing a lot of views by hand. The idea of Class-Based Views is either unheard of (yes, it is not heavily documented that one should use them at the start) or frightening upon discovery. However a clear definition of what they are is provided by Classy Class-Based Views:

“Django’s class-based generic views provide abstract classes implementing common web development tasks. These are very powerful, and heavily-utilise Python’s object orientation and multiple inheritance in order to be extensible. This means they’re more than just a couple of generic shortcuts — they provide utilities which can be mixed into the much more complex views that you write yourself.”

Classy Class-Based Views is probably the most helpful tool for working with Class-Based Views. Use it. SHARE IT. It shows you which attributes and methods are available to override. Familiarizing yourself with its documentation will help tremendously when deciphering issues you may have when overriding defaults.

I will not really be discussing any more topics related to Django’s Class-Based Views, but I believe it is important to understand this concept of abstraction for our next step. Understanding and using Class-Based Views will be instrumental for those of you creating Django projects that are non API based / include heavy server side rendering.**

** If lots of discussion is generated from Class Based View, I may write a separate document for that topic.

Further Reading on Class-Based Views:

8–3. Django REST Framework Generic Views and ViewSets

Just as Django has Class-Based Views, Django REST Framework has their own. Again, many built-in functions required should not be rewritten. You can easily write a View by hand with DRF, or you can use the expansion to Generic Views provided. The DRF Generic Views are defined here.

We will use the Generic Views to write out more custom API functions! However most of our usecases will use ViewSets.

ViewSets are defined by DRF as:

“a type of class-based View, that does not provide any method handlers such as .get() or .post() , and instead provides actions such as .list() and .create() .”

This means many of the views we would have had to create with Generic Views are now bundled into one! Another great reason to use ViewSets is that, when combined with DRF Routers (more on that soon), our URLs can automatically be created!

The Class-Based Views, Viewsets, and Serialiers provided by DRF also have their own reference at Classy Django REST Framework.

8–4. Creating our User ViewSet

Now that we have gone over the concept of Views, it’s time to create our User ViewSet. We will build the UserViewSet off of the ModelViewSet class.

From the documentation we can see that ModelViewSet includes the following functions: .list() , .retrieve() , .create() , .update() , .partial_update() , and .destroy() . So now we can perform these functions without needing to write them by hand! However, we must also override some of the attributes inherited from GenericAPIView , where queryset and serializer_class must be set. View the other attributes here.

Open up project/api/views.py and make these additions:

from django.contrib.auth.models import User

from rest_framework import viewsets

from project.api.serializers import UserSerializer class UserViewSet(viewsets.ModelViewSet):

"""

API endpoint that allows users to be viewed or edited.

"""

queryset = User.objects.all()

serializer_class = UserSerializer

In the above we have:

Imported the User model, viewsets library, and our new UserSerializer

model, library, and our new Created a view, UserViewSet that inherits from ModelViewSet

that inherits from Overridden the ModelViewSet attributes of queryset and serializer_class

There are more attributes and functions one can override in ModelViewSet , however we must set queryset and serializer_class to those for the User model.

queryset : the queryset that will return objects on .list()

: the queryset that will return objects on serializer_class : the serializer class that is used for the functions

9. URLs and DRF Routers

Now our User’s serializer and views are complete. Time to create a router that will create URLs for us from a ViewSet!

Routers have two attributes that must be set, the prefix and viewset . The third option base_name can be set later. The prefix is a regular expression that will start our URLs. We will add the router for users to our api/urls.py , shown below:

from django.conf.urls import url, include

from rest_framework import routers

from project.api import views router = routers.DefaultRouter()

router.register(r'users', views.UserViewSet) urlpatterns = [

url(r'^', include(router.urls)),

]

With that we should be able to manipulate User models in a RESTful way! Further reading on how to make URLs and general info on regular expressions.

10. Testing Your API!

We can test our API in two ways, via the terminal or through the Django REST Framework interface in the web browser. To begin testing, first run the Django server.

# Command

python manage.py runserver

Now we can move to the browse-able API Root in the browser! Navigate to http://localhost:8000/ and you should see this page!

API Root showing Users

You can click on the link for users, to be brought to the User List, and clicking on a user will bring you to a User Detail. The GUI allows you to create, delete, or update values on the User model or others. You can also use these functions through the terminal with tools like curl.

Using curl , we can make a GET request to /users/ and have the data be formatted in the terminal as JSON:

When a request has been made to /users/ at the terminal or in the browser this happens: An HTTP request with a GET method has been made to request the resource /users/ . The router has sent that request to the UserViewSet , which determined that it should return a list of all Users.

If another request was made with a set of data to the same URL it would be as a POST to create a new user!