Setting up a Basic Django Backend
One of my friends recently called me a “Django-whisperer.” Having wanted to learn Python since I began my software engineering journey, I am honored to have been given this title.
To help future Django-whisperers, this blog post will be a short tutorial for setting up a basic Django backend. The goal of the app will be to add a review to a website (like Yelp). Therefore we will need a Review model that has a “name” field, a “review” field, and a “date created” field.
First, make sure you have Python and pip installed on your machine. Python3 and pip3 are the most recent versions, and that’s what I use. So create a project folder, and then inside the folder, you need to create a virtual environment (see my post about the importance of virtual environments here). Python has a built-in mechanism for creating a virtual environment, so just run this command inside your project directory:
python3 -m venv venv
where the second venv
is the name you want to give your virtual environment. So if I were to name my venv “cool_venv,” the command would be. python3 -m venv cool_venv
. Once that’s complete, you want to activate the venv by running:
. ./venv/bin/activate
and you replace venv
with the name of your virtual environment. So my command would be . ./cool_venv/bin/activate
. If it activated correctly, you should see an indicator in your command line. Now we can start installing necessary packages (Django, Django Rest Framework, Cors, etc). So you can run:
pip3 install django djangorestframework django-cors-headers
To make sure they installed correctly, you can run pip freeze
to see the list of packages and their versions. Now you can start your Django project! Run this command:
django-admin startproject 'project_name'
where ‘project_name’ is what you want to name your project (omit the quotation marks). Then CD into that directory, you should see a manage.py file. Wherever you see a manage.py is the root directory, and that’s where you will run all of your main commands (runserver, migrate, etc). From this root directory, open the project in your favorite text editor (in your text editor, make sure you’re using the Python interpreter within the venv). Run this command to create your app directory (for models, views, serializers, etc):
python3 manage.py startapp 'app_name'
where ‘app_name’ is replaced by what you want to name your app (omit the quotation marks). Keep in mind, a project can contain many apps, so pick a name based on what you want the main function of this app to be. For example, if the primary function of this app is to write reviews, then maybe name it ‘reviews.’
You should see two folders in this directory (one is the project name, one is the app name) in addition to the manage.py file. Open your project folder and go into the settings.py file to add the following to your “INSTALLED APPS” list:
INSTALLED_APPS: [
...
"rest_framework",
"corsheaders",
"app_name",
...
]
There are other items you need for cors (whitelist, allow-origin, etc). See the link here to figure out which would work best for you, but for now we can just add:
CORS_ORIGIN_ALLOW_ALL = True
but keep in mind this is not secure. You will also need to add special middleware for cors:
MIDDLEWARE = [
...
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
...
]
The site instructs to give them a specific place, so see the docs for more information.
BONUS: Be aware, your settings.py file also contains a SECRET KEY. Keeping it in this file is not secure, and you should store it in a .env file and then include that in your .gitignore file. You can access variables from your .env file by installing the python-decouple package. Once installed with pip install python-decouple
, you can import it into settings as:
from decouple import config
and then you can retrieve the secret key with this code:
SECRET_KEY = config('SECRET_KEY')
where ‘SECRET_KEY’ is whatever you gave it in the .env file.
Now let’s migrate and run the server. Run these commands (and again, make sure you’re running these commands in the root directory that has the manage.py file):
python3 manage.py migratepython3 manage.py runserver
Assuming everything worked correctly, you should be able to go to localhost:8000 (unless you designate another port) and you should see this page:
Awesome! So one of the best parts about Django is the superuser. This allows you to log in as an admin and manage the data in your database. To set this up, run this command:
python3 manage.py createsuperuser
Follow the prompts, and once it’s complete, you can now navigate to localhost:8000/admin and you can login with those credentials and you will see this page:
Now for the good, classic API stuff. Open your app folder and go into your models.py. Like I mentioned before, our Reviews will have a name (string datatype), a review field (string datatype), and a date_created field (date datatype). So it will look like this:
class Review(models.Model):
name = models.CharField(max_length=20)
review = models.TextField()
date_created = models.DateTimeField(auto_now_add=True)
CharField requires a max_length. Check the docs to see any other field rules, and for a list of field types. Keep in mind, I used ‘TextField’ for reviews because it doesn’t have a max amount of characters, unlike CharField.
Once this is complete, time to make a migration! Run these simple commands:
python3 manage.py makemigrationspython3 manage.py migrate
BONUS: If you make any mistake and you need to rollback to a previous migration, you can run this command:
python3 manage.py migrate 'app_name' migration_file_name
where the file name is usually preceded by a number (e.g. 0001_). You don’t need to file extension type, just the name. And of course, replace ‘app_name’ with the name of your app (omit the quotation marks). Once this is successfully rolled back, you can delete the unwanted migrations.
Next we will create a serializers file. In your app directory (where the models.py file is), add a serializers.py file and open it. You will need to import the serializers feature from the rest_framework package as well as the Review model at the top of this file:
from rest_framework import serializers
from .models import Review
This is just a simple Review API, so we want to be able to view all the fields when looking at an instance of a review (like in JSON format, for example). The Review Serializer will look like this:
class ReviewSerializer(serializers.ModelSerializer):
class Meta:
model = Review
fields = '__all__'
Obviously if you need more customization (only see specific fields, serializer depth, etc) then you can reference the rest framework docs.
Now we move onto what you can actually do with this model, meaning what HTTP requests you can make. This will be specified in our views.py file. First, you will need to import as follows:
from django.shortcuts import render
from rest_framework import viewsets, permissions
from .serializers import ReviewSerializer
from .models import Review
And then we can create a viewset! There are a lot of different ways to set up a viewset depending on what specifically you need and if you need permissions or extra actions, but we will stick with the simpler Model viewset:
class ReviewViewSet(viewsets.ModelViewSet):
permission_classes = [permissions.AllowAny]
queryset = Review.objects.all()
serializer_class = ReviewSerializer
This means that you can sent any HTTP request on this model (GET, POST, PUT, PATCH, DELETE) and anyone can do so (see permissions). The queryset is what the view is based on (this will return all the Review instances/objects). And lastly, it will set them up with the designated serializer.
Now we need a way to view this model! This requires an endpoint. So in your app folder, create a urls.py file and open it. You will need to import as follows:
from rest_framework import routers
from .views import ReviewViewSet
and then to “register” an endpoint, write out this code:
router = routers.DefaultRouter()router.register('reviews', ReviewViewSet, 'reviews')urlpatterns = router.urls
Your main urls.py file (in your project directory) will be looking for that “urlpatterns” so make sure you include it. The first ‘reviews’ will be in the actual url, the second ‘reviews’ is whatever you want to call your endpoint.
Then open up the urls.py file found in your project directory (the directory that has the settings.py file). In here, you should already have an admin url (otherwise you’re localhost:8000/admin wouldn’t have worked). In the importing part, from django.urls you will need to also import include, so your imports will look like this:
from django.contrib import admin
from django.urls import path, include
Then you can set up another root:
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('app_name.urls')),
]
I usually like to leave an empty string, which means the endpoints will be built off of the root localhost:8000/ . Replace ‘app_name’ with the name of your app folder. As long as this is setup properly, when you run your server, you should be able to navigate to localhost:8000/reviews, which will of course show an empty page since we haven’t created any reviews yet. You of course can test this in Postman or Insomnia or whichever app you prefer to use.
And of course, as a finishing touch, don’t forget to register it on the admin site. In your admin.py file within your app directory, import as follows:
from django.contrib import admin
from .models import Review
and register the model like this:
admin.site.register(Review)
Once this is saved, you should be able to navigate to localhost:8000/admin and it will now look like this:
And now you can see the Reviews section! Once you click on it, it will show you all the reviews objects and you can edit/add/delete as admin.
Once again, this is a very basic Django backend, but I hope it helps someone dive into the world of Django APIs.
For further reading, feel free to check out a couple of my other Django-based blogposts:
Here’s the link to my github repo with all of this working code: https://github.com/alexiscait142/basic_django_backend
Happy Django-ing!