How to Build an App Part 2: Creating the back-end with Django REST Framework
Welcome to part 2 of 3 of my How to Build an App tutorial. In the first part, I explained how to create the back-end server which we will use to host our app’s back-end (if you didn’t get a chance to read it, you can check it out here). In this second part, I will explain exactly how to build the back-end itself.
If you’re loving this tutorial, then maybe you’ll like my course: How To Build A Backend with Python & Django REST Framework on Udemy!
If you haven’t gone through the steps in the first post yet, I suggest you do it now. If you really don’t feel like it, you can download the code from here https://github.com/LondonAppDev/miab-devenv and extract it to “c:\workspace”.
So, let’s start off by loading the development server using Vagrant. Open Command Prompt and switch to the “devenv” directory by typing:
cd c:\workspace\devenv
Next, run the following command to load vagrant:
vagrant up
After typing this, Vagrant should start booting the development server:
The server may take 10 – 15 minutes to load. Then you should see something like this:
Now that it’s loaded, let’s connect to the server by running the following:
vagrant ssh
Creating the Django Project and App
OK, now we are going to start our Django project. Switch back to the Command Line window that is connected to the server. Then change to the “/vagrant/project/” directory on the server by typing the following:
cd /vagrant/project/
This is the directory that is synced to “c:\workspace\devenv\project” on our system. In other words, anything you create in “/vagrant/project/” will appear in “c:\workspace\devenv\project” and vice versa.
Now we are going to switch to the Virtual Environment which we will use to install the packages we require. A “Virtual Environment” is an application that allows us to keep all of our Python packages for a particular project separate from other projects. If you want to learn more about Virtual Environments, you can read this: http://docs.python-guide.org/en/latest/dev/virtualenvs/
Type the following command to activate the Virtual Environment “env”:
workon env
Now we are going to install the following packages into our Virtual Environment (I am pinning specific versions to future proof this article):
- django
- djangorestframework
- mysqlclient
Note: There is a prerequisite for the Python mysqlclient package. It consists of one line in “/devenv/salt/dev.sls” and can be seen here: https://github.com/LondonAppDev/miab-devenv/commit/0d5c2e2f88b67b86d8f9f1b34fbed1628818bc67. Make sure the line is added in your file. If it is not, then add it, and run the following on the server:
sudo salt-call state.highstate
Now run the following command to install the three python packages mentioned above:
pip install Django==1.9.4 djangorestframework==3.3.3 mysqlclient==1.3.7
Now let’s create our Django project. Make sure we are in the “/vagrant/project/”, and run the following command:
django-admin.py startproject miab_backend
Let’s take a look at the “c:\workspace\devenv\project\” folder and you will see the files have been created:
Open the project file in Atom.io as this is where we will be doing most of the upcoming work:
Next, let’s create the Django app to store our API. Change to the miab_backend directory and start a new app called api by running the following commands:
cd /vagrant/project/miab_ backend/
python3 manage.py startapp api
If you look back to your project files in Atom, you will see that the app has been created:
Setting up the Database Model
First, add the api app to the INSTALLED_APPS section of the settings.py file. Update it to look like this:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'api',
]
Now let’s setup the database. We must update the DATABASES section in the settings.py file. Update it to look like this:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'miab_db',
'USER': 'root',
'PASSWORD': 'password',
}
}
Now we need to create a database model in the api app to hold our messages. A database model effectively describes a database table (the name, columns, the data types). It allows us to easily interact with the database through Django.
Open the api/models.py file and update it to look like this:
# Import the 'models' package.
from django.db import models
# Create the class to describe the model.
class Message(models.Model):
"""Stores messages for our bottles."""
# Create a text column to store the message. Limit this to 120
# characters as we this isn't "Essey in a Bottle" :)
message = models.CharField(max_length=120)
# Add a boolean column for marking messages as read, so we can
# filter them to ensure users only get new messages.
is_read = models.BooleanField(default=False)
# This is meta data about the database table.
class Meta:
# Set the table name.
db_table = 'message'
# Define what to output when the model is printed as a string.
def __str__(self):
# Return the message.
return self.message
Comments (prefixed by #) describing what each line does are in-line.
Now, let’s create the migrations. Migrations are automatically generated Python files which describe changes in the database since the last “migration” was ran (which is never in our case). Let’s create the migrations for the above model by running the following from the Linux terminal:
python3 manage.py makemigrations
The migration files will be created:
Now we will run the migration. This will cause the necessary table to be created in the database to store our messages. Run the following:
python3 manage.py migrate
As this is the first time we are running the migrations, Django will apply a number of migrations from it’s core apps as well as ours:
Create the Admin Interface
Now we are going to create an admin interface for our back-end. We will do this using the Django Admin app, which comes pre-enabled with Django. To use this, all we need to do is tell the admin site to manage our model, and create a super user.
Tell the admin site to manage our messages model by opening the api/admin.py file and updating it to look like this:
from django.contrib import admin
# Import our models module.
from . import models
# Register our "Message" model with the Django Admin/
admin.site.register(models.Message)
Next, let’s create our superuser. This needs to be done on the command line, by typing the following command:
python3 manage.py createsuperuser
You will be prompted for a username, email address and password to be used for your admin user. Enter the details when prompted.
Now we are going to run the webserver and test our admin panel. However, before we do that, we need to find out what our server’s IP address is so we can access it. On the server, run the following command:
sudo ifconfig
In the output, you will see the details for two network interfaces called eth0 and eth1. We are interested in the inet addr for eth1. For me, it is 192.168.1.68, however, it may be different for you. Take note of your Server IP Address.
Taken note of your servers IP Address? Great! Now we are ready to start our server. Run the following command in the terminal to start the Django development web server:
python3 manage.py runserver <Server IP Address>:8000
Replace <server IP Address> with the IP address of your server. So for me, it would be:
python3 manage.py runserver 192.168.1.68:8000
Now that the server is running, let’s load up a browser on your local machine and navigate to http://<Server IP Address>:8000/admin. So in my example, the address would be http://192.168.1.68:8000/admin. If all is working, you will be met with the Django Admin login screen:
Enter your superuser credentials and click Log in:
Welcome to the wonderful Django admin which gives you an out-of-the-box administration panel for your application with only a few lines of code.
Let’s put our Django admin panel to immediate use by creating some example messages to kick off our Message in a Bottle application. Next to Messages click Add to add a new message:
Now, type a message and click Save and add another.
Now, let’s repeat the above steps for 5 more messages, to add an element of randomness for our first few users. If you can’t think of any messages to add, here are a few examples:
- When you have exhausted all possibilities, remember this: you haven’t.
- Nothing worth having comes easy.
- Your only limit is you.
- A person who never made a mistake never tried anything new.
- A river cuts through a rock, not because of its power, but its persistence.
After adding all those messages, click Messages in the breadcrumb navigation.
You will now see a list of all the messages you’ve added:
OK now that’s done, the database and admin panel is setup. Let’s move onto the next section.
Create the REST API
We now have a server, a database and an admin interface. The next step is to create a REST API which allows us to interact with our database.
Let’s start by enabling the Django REST Framework in our settings file. In the ‘miab_backend’ directory, edit the settings.py file. Locate the INSTALLED_APPS section and update it to look like this:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'api',
]
Next, let’s create our serailizer. The serializer’s job is to receive the user’s input and turn it into a Python object that we can work with in our application (and vice versa). The serializer has built-in functionality for input validation (eg. checking the user entered a string where a string is required).
In the ‘api’ directory, create a new file called serializers.py. Then input the following contents:
from rest_framework import serializers
from api import models
# The serializer class takes the users input and converts it to a Python
# object that we can work with (and vica versa).
class MessageSerializer(serializers.ModelSerializer):
"""A serializer for our message model."""
class Meta:
# Tell the serializer class that the data should match our
# "Message" database model.
model = models.Message
# Tell it we only expect to see the 'message' field (as all other
# fields will be automatically generated).
fields = ('message',)
Now we will create our view. The view is responsible for receiving the users input, sending it to the serializer and displaying a meaningful output.
In the ‘api’ directory, edit the views.py file to look like this:
from random import randint
from django.shortcuts import render
from django.db.models import Count
from rest_framework import views
from rest_framework.response import Response
from . import serializers, models
class MessageView(views.APIView):
"""View to managing messages through the API."""
# The 'serializer' class takes out input and turns it into
# a Python object we can play with.
serializer_class = serializers.MessageSerializer
# This is what happens when we receive a HTTP POST request to the API.
def post(self, request, format=None):
"""Receive the post of the new message and return a random one."""
# First, let's get a random message.
# (We do this first to avoid getting the same message the users posts.)
random_message = self._get_random_message()
# Send the users input to the serializer class.
serializer = self.serializer_class(data=request.data)
# Check that the users input is valid. Raise an exception if it's not,
# as DjangoRestFramework will automatically display the error to the
# user.
if serializer.is_valid(raise_exception=True):
serializer.save()
# If we got this far, no exception was raised and the input is valid.
# So let's mark the "random_message" as read.
random_message.is_read = True
# Now save the updates to the 'random_message' in the database.
random_message.save()
# Now return the data of the serializer class.
return Response(self.serializer_class(random_message).data)
# This is our method that will get a random message.
def _get_random_message(self):
"""Get a Random Message from the Database."""
# Get the count of un-read random messages in the database.
count = models.Message.objects.filter(
is_read=False
).aggregate(
count=Count('id')
)['count']
# Get a random number between the count.
random_index = randint(0, count - 1)
# Select the unread message for the random number that was selected.
random_message = models.Message.objects.filter(
is_read=False)[random_index]
# Return the random_message.
return random_message
Now that we have our view, we need to create a URL that points to it. In the ‘miab_backend’ directory, edit the urls.py file to look like this:
from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^api/message/$', views.MessageView.as_view()),
]
Finally, let’s test the API. The best thing about Django REST Framework is that it automatically gives you a working interface that you can immediately use in the browser.
Go to your browser, and navigate to http://<Server IP Address>:8000/api/message (So, in my example, the address would be http://192.168.1.68:8000/api/message). The Django REST Framework interface should load. In the Message field, type a positive message and click Post.
You should see one of the other messages returned as a response:
And that’s it! You now have the working REST API. Stay tuned for the next post which will make use of our API and turn it into a working App.
Cheers,
Mark
Really enjoying the read Mark and looking forward to part three. Work with a team of three front end developers who are complete novices when it comes to apps so the step by step guide is really helpful to us gaining an understanding in the process. Thanks again and keep up the good work.
Hi Jamie, thanks a lot for the comment, it means a lot. As you may have seen, the third part is online now. I hope you find it useful. I would love to hear about the results you get after following the guide!
Hi Mark,
This is awesome. I need to get I touch with you as I’m building an app using Django on Centos 6.7 Linux, on virtual of and I’m quite a newbie and are struggling in some configuration.
Hi Mimish. Thanks for the comment. Let me know what you are struggling with and I will try and help.
Hello Mark,
Nice tutorial. I am looking for a face to face tutorial for Django in London.Could you please help me in this.
Thanks
Sajjan