Django is a web framework written with the beautiful programming language Python. Generally, a framework lets you do things faster, better and easier and this is what Django is all about. Since Django is a very old framework in comparison to others, it’s had a lot of time to grow and improve. This is because Django is an Open Source software, which means lots of developers work together in their spare time to improve Django.
Welcome to this tutorial series in which you will build a REST API using Python and Django. At the end of this series you will have your very own fully deployed and production ready API. We’ll have a look at the Webframework Django, and cover the Django REST Framework extension, look at how to use Django with docker and how to deploy everything on your web server.
For this tutorial you should already be familiar with the basics of Python programming.
Let's dive right into it.
We will start by creating a Django project right out of PyCharm. Select Django on the left side in PyCharm and give the project a name. We’ll name it pyblog since this API is gonna be used on a blog website later.
The next thing is to choose the settings for your Python environment that PyCharm will create for us. This is also the place where PyCharm will install the latest version of Django. If you have anaconda installed, it will show up here ready for you to create new Python environments. If you don't have anaconda installed yet you can also use virtualenv. Just make sure you choose Python 3.6 or later for your project, since Django is a bit different for older versions of Python. I will use anaconda to create my Python environment and use the Python version 3.7.
Open up the more settings section and give your Django app a name. A Django app is the Django way of writing custom code for a Django project. This should be different from your project name. I’ll use posts as a name my Django app.
You can also leave the checkbox for the Django admin interface selected. This allows us to later access the Django built in the admin interface via a user login and change data in our database.
Lets go ahead and create our project.
PyCharm creates a new Python environment and installed all the needed dependencies of Django in this new environment.
Lets test if everything works fine by clicking the run button in the toolbar. After the Django server starts you can see the results in a terminal appearing in PyCharm. With a click on the blue link you should get the Django welcome page.
Let's switch back to PyCharm.
The folder called pyblog is our main project folder. It contains all the files that Django generates in order to run properly. The most important one is the settings.py file. It contains all the settings and configurations for our project.
The next important file is the urls.py. In here you will find all the url configurations for your Django app. You can see that url configuration for the admin interface already exists. This is because we left the checkbox for the admin interface selected.
This next file, the wsgi.py file is the web server gateway interface configuration. This file is required to run our Django app in production. We will cover this later in this tutorial series.
Let’s head over to our Django app folder. This is where all our custom code will live. Let's have a look at the first file which is called models.py. This is the place where you will create your instructions to create database tables in order to store data.
After you’ve created your models, Django will create migrations files for it. These files are stored in the migrations folder. They contain the actual instructions to manipulate our database scheme. So every time you change your models code you need to tell Django to create new migration files.
The admin.py file is used to tell Django what models that we’ve created are available in the Django admin interface.
The views.py file is the place where you write your instructions, what Django should return when we visit a specific URL in the browser. (More on this later.)
The app.py file is a configuration file for a Django app. Here you will configure your app with things like name, verbose_name and path or load your Django signals. This is usually used for more advanced Django apps.
And finally we have the tests.py file. This is where you write your unit tests for your Django app. We can ignore that for now.
Okay let’s begin writing a view and display custom text on the webpage instead of the Django welcome screen. Let head over to the views.py file and create a class called ListPostView. This class is going to subclass the Django View class. You can autoimport this class in pycharm by placing the cursor on the class name and hit alt+enter or option+enter. This will bring up a small window. We can now navigate with the arrow keys to import it from the right place. In our case we want to select Django.views.View.
Let's add a definition called get. This is what Django calls when we make a get request in the browser. We also want to add the request as the first positional argument for this definition and accept all the other keyword arguments that Django might pass with the **kwargs keyword.
Now we’re going to return a HttpResponse containing our custom string. As we did before lets auto import this HttpResponse class with alt-enter. Before we head over to our urls to configure the routing to this view, go ahead and copy the name of our view class.
Over in the urls.py file create a new item in the urlpatterns list right below the admin url. Follow the example and use path, and empty string and now paste our view that we copied before. Here we have to call a function on this class with the name .as_view().
When you save this file you should see the Django server reload automatically. When there are no errors, head over to our browser and reload the page. Now you should see our text from the view showing up.
Back over in PyCharm we can adjust the view slightly so that it delivers JSON instead of raw text. We can do this by creating a new variable and assign a dictionary to it. In order to deliver JSON instead of text we have to change the response class to JsonResponse. Again, use the auto import feature and remove the HttpResponse from before.
Let's have a look at the result over in the browser.
After our first encounter with Django views lets begin writing models.
Let’s create a Post class that holds all the blog posts by subclassing the models.Model class from Django. Also add the fields title, content and created.
- The title is a charfield which is a limited character field in the database.
- The content is going to be a text field which will not be limited to how much text you can put into it.
- Finally we create the created field, a DateTimeField, and will have a special argument “auto_now_add” that tells Django to add the current date and time to this field when a new post gets created.
After we’ve created the model, open up the terminal in pycharm and activate the Python environment. With anaconda installed you can just type conda activate pyblog. The name of the environment is the same as your project name. If you are working with virtualenv you can use the command source activate pyblog. This will do the same thing.
You can see that your environment is active when you have a prefix with the environment name in brackets. Now we can create a new migration file for our new model with Python manage.py makemigrations and apply migrations to a new sqlite database with Python manage.py migrate afterwards.
Now that our model is created we should register it in the admin.py file. Create a new class called PostAdmin which subclasses the admin.ModelAdmin class. To make the connection between our model class and this admin config class we can use a decorator @admin.register(Post). Don't forget to import our model with the auto import.
Now in order to log in to the Django admin backend we need a user. Let's create one in the command line with the command Python manage.py createsuperuser.
This will ask you for username and password. We can leave the email empty, because we don't need it for now in this example. You can always change these values later.
Let’s head over to our website and go to the url http://localhost:8000/admin/. Now we are able to login with the superuser we just created.
From here it’s very easy to go to posts and add a new post to our database.
So now we want to update our ListPostView to deliver actual posts out of our database in JSON format. To do this we want to change the data variable to Post.objects.all() and add .values() function . This will return all the records our of our database from the Post model. The .values() function turns all the posts into dicts ready for us to turn into JSON.
When everything works fine you will see a list of dictionaries in your browser.
Lets create a couple more posts in our database in order to filter them.
Back in our View class we can now update the .all() method to .filter(). This allows us to filter the posts on all the fields that the Post model has. I’m going to filter the title field with a hardcoded string. The __iconains keyword is useful to filter on parts of Post titles instead of exact matches. It also filters for case insensitive words. I'm searching here for all the posts that have the keyword animal in the title.
In order to test this, switch over to our website and do a reload.
The last thing to do is move the urls that belong to the specific Django app into the Django app itself. To do this create a urls.py file in your Django app and add a variable urlpatterns. Assign a Python list to it and add the function path. This is where we connect the url with the view. I leave first argument an empty string and add our ListPostView class to it. As we did before don't forget to call the .as_view() function. Now we can give our URL a name and finish this file off by importing our view class.
To tell Django to use this new urls.py file we have to import it into the main urls.py file. To do this we specify a URL prefix on which our posts api should run on. I’m using api/ for this purpose. To import the other urls.py file we have to use a method called include. We have to write the path to this file dot separated. So this is going to be posts.urls. We also should add a namespace for this include. I’m using api again for simplicity. This is going to be useful later when we are writing tests for our api.
We also have to specify an app name for this include which is going to be the second argument in the include tuple. I’m specifying the same name as our Django app name which is posts.
After a quick reload of our Django server we should be able to access our API using the url api/.
This is the end of the first part in this tutorial series. In the next post we will start using Django rest framework to continue building our blog api.