If you are working on a single-page application and you want it to have some persistence, it’s a really good idea to have a REST API. This way, you’ll be able to store your domain’s entities in the database. In this article, you will learn how to create a basic application with Django and Django REST framework. You can use this as a starting point, and then it’s quite easy to extend this project with different pluggable Django applications.
You can find a repository here and demo here. The animation below shows the automatically generated HTML interface of the API created in this tutorial:

Make a Project from a Template
Use the code below to create an environment for further development.
$ mkdir drf-demo; cd drf-demo
$ virtualenv .env
$ pip install "Django >= 1.9, < 1.10"
$ django-admin startproject project
--template=https://github.com/ambivalentno/django-skeleton/archive/master.zip
$ mkdir log $ mkdir project/db
Now your environment is fully functional.
Next, start your development server with the following:
$ python project/manage.py runserver
Finally, go to http://localhost:8000/. You will see a “Welcome, Django
” message.
Define Some Models
Here, we want to model students that go to a university. So, let’s first define entity classes and their attributes. Every university has a name; and every student has a first name, last name and attends a single university (many-to-one relationship). To see a list of available fields, you can go to the Django manual for model fields.
Listing of project/apps/core/models.py
from django.db import models
class University(models.Model):
name = models.CharField(max_length=50)
class Meta:
verbose_name = "University"
verbose_name_plural = "Universities"
def __unicode__(self):
return self.name
class Student(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
university = models.ForeignKey(University)
class Meta:
verbose_name = "Student"
verbose_name_plural = "Students"
def __unicode__(self):
return '%s %s' % (self.first_name, self.last_name)
Each Model
here is related to a table in the database. As we don’t have these tables in the database yet, let’s create a rule to make them (in Django, these rules are called migrations):
python project/manage.py makemigrations core
Now to apply them, do this:
python project/manage.py migrate core
You will see a lot of SQL queries logged to the console, and that’s absolutely fine. Now you have a database structure defined and we are ready to put some data in it.
Enable the Admin Interface and Populate the Database
Django’s admin interface offers a visually convenient way to discover and edit database data. To enable it, add this to the project/apps/core/admin.py:
Listing of project/apps/core/admin.py
from django.contrib import admin
from .models import University, Student
admin.site.register(University)
admin.site.register(Student)
Next, create an admin user (comand-line dialogue omitted, as it’s quite obvious):
python project/manage.py createsuperuser
Go to the admin url (ensure your development server is up):
You can add universities here and students here.
Congratulations! Without writing much code at all, go take a look at your brilliant and free functionality.
Django REST framework-based API
Obviously, you cannot plug in anything unless you install it, so let’s install Django REST framework (or DRF) with pip:
$ pip install djangorestframework
Next, you should add ‘rest_framework
’ to the INSTALLED_APPS
at the project/conf/base.py so that it’s available for Django process.
Write Some Model-based Serializers
To perform HTTP-based interaction, we have to define rules to convert Django models (python objects) to the json strings and vice versa. This is a serialization/deserialization task. So, let’s define some model-based serializers:
Listing of project/apps/core/serializers.py
from rest_framework import serializers
from .models import University, Student
class UniversitySerializer(serializers.ModelSerializer):
class Meta:
model = University
class StudentSerializer(serializers.ModelSerializer):
class Meta:
model = Student
Of course, you can manually define your own serializers. As a reference, you can use DRF’s documentation or even some performance-oriented serializers.
Make a Quick viewset
A viewset
is a set of views (controllers in traditional MVC terminology). If you take a look at the ModelViewSet code, you’ll see that there’s a lot of functionality automatically added there. You are able to create, view, edit and delete objects in your system (and database). It’s a full CRUD set with http as the interface protocol. Let’s configure two viewsets for our classes:
Listing of project/apps/core/views.py
from rest_framework import viewsets
from .models import University, Student
from .serializers import UniversitySerializer, StudentSerializer
class StudentViewSet(viewsets.ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentSerializer
class UniversityViewSet(viewsets.ModelViewSet):
queryset = University.objects.all()
serializer_class = UniversitySerializer
Now we need to expose this logic to the outer space, which is done via url routers: we have to define mappings from http request addresses to the views (controllers).
To attach app-level url
s to the general workflow – edit project/urls.py:
from django.conf import settings
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/', include('apps.core.urls', namespace='core')),
]
if settings.DEBUG:
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
Here, we are rerouting all requests that have ‘api
’ in the url to the apps.core.urls
. Here’s a “child
” url
router, where:
Listing of project/apps/core/urls.py
from django.conf.urls import url
from rest_framework import routers
from core.views import StudentViewSet, UniversityViewSet
router = routers.DefaultRouter()
router.register(r'students', StudentViewSet)
router.register(r'universities', UniversityViewSet)
urlpatterns = router.urls
At this moment, you’ve got a working API. Let’s check it out!
Look at the Browsable API
Go to the http://localhost:8000/api (demo url http://drf-demo.herokuapp.com/api) where you will see the browsable API:

Next, go to http://localhost:8000/api/universities/ (demo link http://drf-demo.herokuapp.com/api/universities/) where you will see it’s possible to create new universities via POST
requests with a simple form submission.
In case you want to view raw JSON – you can go to http://localhost:8000/api/universities/?format=json (demo link http://drf-demo.herokuapp.com/api/universities/?format=json). For students, it’s the same: http://localhost:8000/api/students/ (demo link http://drf-demo.herokuapp.com/api/students/)
Generate and Read Automatic Documentation with django-rest-swagger
We’ve already installed one Django application, via pip. Now install Django-rest-swagger and add it to the INSTALLED_APPS
(‘rest_framework_swagger
’). To expose it at the url
routing level, edit core/urls.py this way:
from django.conf.urls import url, include
from rest_framework import routers
from core.views import StudentViewSet, UniversityViewSet
router = routers.DefaultRouter()
router.register(r'students', StudentViewSet)
router.register(r'universities', UniversityViewSet)
urlpatterns = [
url(r'^docs/', include('rest_framework_swagger.urls')),
]
urlpatterns += router.urls
As you can see here, we’ve used rest_framework_swagger
to merge the API’s url
s from the router and url
s. You can check if it works at http://localhost:8000/api/docs/:

This way, you’re able to view the definitions of DELETE
, PUT
and PATCH
commands differently from the default DRF browsable API. Also, you may find the “Try it” button convenient.
Summary
I hope this article helps you set up a REST API for your project. Remember, you can easily extend it, and if it’s hard for you – please, contact us.
Author
Yuri Kriachko is head of a Python/Django company, 7WebPages.
The post appeared first on Tests4Geeks.