Django & EmberJS Full Stack Basics: Connecting Frontend and Backend — Part 3

Michael X
7 min readAug 28, 2018

--

In Part 3 we use the Django REST Framework to build our books API.The books API has serializers, views, and URLs that query, structure, and deliver the book data from the database to API endpoints.

P1, P2, P3, P4, P5

3.1 Django REST Framework

Django REST Framework (DRF) builds on top of Django and is used to build RESTful Web APIs. It provides tools to make the process straightforward. For example, we’ll use the built-in serializers and views instead of building these from scratch.

For more complex projects you’ll want to overwrite defaults or make your own. Again, for the purposes of simplicity and sticking to our primary goal (stitching together the frontend and backend) we’ll use what comes out of the box without undue modification.

3.1.1 Install Django REST Framework

Make sure you’re in the my_library directory and have the virtual environment activated. To start working with DRF install it with pip:

# install Django REST Framework
pip install djangorestframework

# install Markdown support for the browsable API
pip install markdown

Now open up my_library/server/server/settings.py and install DRF right above the book app.

INSTALLED_APPS = [
...
'rest_framework',
'books'
]

Add the default settings at the bottom of the file:

REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}

This is a permission class that ‘allows unauthenticated users to have read-only access to the API’. Find out more about permissions here.

3.2 The books API

3.2.1 Create the books API folder

With DRF installed let’s start building the books API. Create a new folder called api inside books app with an empty __init__.py file: my_library/server/books/api/__init__.py.

This empty file helps Python understand that this folder is a Python module. The api folder will contain the serializers, views, and URLs for our books data.

3.2.2 Create a serializer

In simple terms, serializers take database data and restructure it to work more easily and efficiently with higher layers of our application like the frontend. For example, the Ember frontend we will create expects the data returned to it from a request to be in the JSON format.

Create the serializer in my_library/server/books/api/serializers.py:

from rest_framework import serializers
from books.models import Book
class bookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = (
'id',
'title',
'author',
'description',
)

This serializer takes the data and transforms it into the JSON format so that it’s understandable to the frontend.

Imports
We are importing built-in serializers from DRF, and the Book model from our books app.

The bookSerializer Class
For this project we want a Serializer class that ‘corresponds to the Model fields’. We can do this easily with the ModelSerializer. According to the documentation:

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

As you see, for the purposes of our simple application the built-in tools are more than capable of handling our basic needs.

3.2.3 Create a view

View functions take in a web request (i.e.localhost:8000/api/books) and return web responses which can be ‘HTML contents of a Web page, or a redirect, or a 404 error, or an XML document, or an image . . . or anything, really.’ In our case we expect to get back books data structured in the JSON format.

Create the views file in my_library/server/books/api/views.py:

from rest_framework import generics, mixins
from books.models import Book
from .serializers import bookSerializer
class bookAPIView(mixins.CreateModelMixin, generics.ListAPIView):
resource_name = 'books'
serializer_class = bookSerializer
serializer_class = bookSerializer def get_queryset(self):
return Book.objects.all()
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)

Imports
First we are import generics and mixins from DRF. Then the Book model from our books app and the bookSerializer that we just created.

generics refers to API views that ‘map closely to your database models’. These are ‘pre-built views that provide for commonly used patterns’. mixins are classes that ‘provide the actions that are used to provide the basic view behavior’. Our book model is simplistic with only the title, author, and description attributes so these provide us with the basics we need.

The bookAPI View
We then create a bookAPIView which takes in the CreateModelMixin and ListAPIView.

CreateModelMixin provides a ‘.create(request, *args, **kwargs) method, that implements creating and saving a new model instance’. It comes with a 201 Create response, with a ‘serialized representation of the object’ when successful and a 400 Bad Request response with errors details when not.

ListAPIView serves our read-only endpoints (GET) and is used to ‘represent a collection of model instances’. This is used when we want to get all or many books.

bookAPIView also takes in our recently created bookSerializer for it’s serializer_class.

We set the resource_name to ‘books` so ‘to specify the type key in the json output’. The frontend client data store layer will have a book model that is case sensitive so setting the resource_name here nips that issue in the bud.

Functions
The function get_queryset returns all of the book objects in the database while post takes in the request and arguments and creates a new database record of a book if the request is valid.

3.2.4 Create URLS

URLs are used to map a URL (i.e. localhost:8000/api/books) to views.

Create the URLs file in my_library/server/books/api/urls.py:

from .views import bookAPIView
from django.conf.urls import url
urlpatterns = [
url(r'^$', bookAPIView.as_view(), name='book-create'),
]

Imports
We import our newly created view bookAPIView and url. We’ll use url to create a list of url instances.

booksAPI URL patterns
In the urlpatterns array we create a URL pattern with the following structure:

  • the pattern r'^$'
  • the Python path to the view bookAPIView.as_view()
  • the name name='book-create'

The pattern r'^$'is a regular expression that ‘matches an empty line/string’. This means that a match will be found if localhost:8000 is visited. It matches to anything that comes after the base URL. Note, this will not work if a / is added to the end of that URL.

We call .as_view() on bookAPIView because that ‘is the function(class method) which will connect [the] class with its url’. When a given URL is visited and is matched to the URL pattern that pattern will then return the bookAPI view that we’ve told it to respond with.

The name='book-create' attribute provides us with a name attribute which can be used to refer to our URL throughout our project. If you want to change the URL or the view it refers to, it only has to be changed here. Without name you’ll have to go through the entire project to update. Check out this thread to find out more.

server URL patterns
Now let’s open up server’s URLs file my_library/server/server/urls.py :

from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/books', include('books.api.urls', namespace='api-books')),
]

Here we import include and create the r'^api/books' pattern which takes in any URLs we created in the api folder. Now the base URL for our books API URLs becomes localhost:8000/api/books. Visiting this URL will match to our r'^/api/books' pattern which will match to the r'^$' pattern we constructed in our books API.

We use namespace='api-books' so that that URLs don’t collide with each other if they are named the same in another app we might create. Learn more about why namespaces are used in this thread.

3.2.5 Demonstration: Browsing the books API

Now that we have the base REST framework setup let’s check out the data the backend is returning. With the server running, visit http://localhost:8000/api/books. The browsable API should return something like this:

Django REST Framework returning book data from the database

3.3 Conclusion

Awesome, we’re really getting going now. At the end of Part 3 we’ve completed the following steps:

  • Installed Django REST Framework into our project
  • Started building the books API
  • Created a serializer for books
  • Created a view for books
  • Created URLs for books
  • Browsed the books API that returns book data from the backend

In Part 4 we will start our EmberJS project which serves as the frontend client. We’ll install the required software, setup a basic DOM, styles, create the book model, and the books route. We’ll also load up some fake data to show how real data from our backend will be displayed when we finally access it.

Gift from the gods

--

--

Michael X

Software Developer at Carb Manager | lookininward.github.io | carbmanager.com | Hiring Now! | @mxbeyondborders | /in/vinothmichaelxavier