Full Stack Build Part 1 - Building and Deploying an API
What you will learn
- Creating an API
- Setting Cors Headers
- Testing an API
- Deploying an API
Setup
Open up terminal in your django folder
activate your virtual environment
source ./djangoenv/bin/activategenerate a new django project
django-admin startproject todoprojectcd into the todoproject folder
test your dev server
python manage.py runserver
Creating the API
- create a new app
django-admin startapp todos
DjangoRestFramework
When creating an API previously we did without any external help and making basic crud routes ended being a bit tedious...
write all crud functions individually
we had to convert our data to json then back to a dictionary to send back as json
the shape of the data isn't we would traditionally would expect
we had to turn off CSRF security and other security features to make work
DjangoRestFramework fixes all the above and creates a nice abstraction for creating REST API's with django. Let's do it!
DJANGO REST FRAMEWORK DOCUMENTATION
install djangorestframework
pip install djangorestframeworkinstall djangorestframework and the todos app in settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'todos.apps.TodosConfig',
'rest_framework'
]
Creating our Model
todos/models.py
from django.db import models
class Todo(models.Model):
subject = models.CharField(max_length=100)
details = models.CharField(max_length=100)
Make and Run Migrations
python manage.py makemigrationspython manage.py migrate
Making Our Serializer
Serializing objects into json strings and then turning them back into python dictionaries can be a tedious process. With djangorestframework, we can build a serializer for our model that handles all this for us along with arranging the data in a more traditional form.
- create a serializers.py in our todos app
from .models import Todo
from django.contrib.auth.models import User, Group
from rest_framework import serializers
# Our TodoSerializer
class TodoSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
# The model it will serialize
model = Todo
# the fields that should be included in the serialized output
fields = ['id', 'subject', 'details']
Creating Our Viewset
djangorestframework has classes for building out views called ViewSets. With these we can wire up all our CRUD routes pretty easily.
in todos/views.py
from .models import Todo
from rest_framework import viewsets
from rest_framework import permissions
from .serializers import TodoSerializer
class TodoViewSet(viewsets.ModelViewSet):
## The Main Query for the index route
queryset = Todo.objects.all()
# The serializer class for serializing output
serializer_class = TodoSerializer
# optional permission class set permission level
permission_classes = [permissions.AllowAny] #Coule be [permissions.IsAuthenticated]
Setting Up Our Router
To make sure all of the ViewSets methods connects to the rights urls, djangorestframework provides with a router to wire it all up. Let's head over to our urls.py.
from django.contrib import admin
from django.urls import path, include
from rest_framework import routers
from todos.views import TodoViewSet
# create a new router
router = routers.DefaultRouter()
# register our viewsets
router.register(r'todos', TodoViewSet) #register "/todos" routes
urlpatterns = [
# add all of our router urls
path('', include(router.urls)),
path('admin/', admin.site.urls),
]
Testing the API
fire up postman
create 3-4 todos with post requests to
/todos/get the full list with a get request to
/todos/see one todo with a get request to
/todos/<id>edit a todo with a put request to
/todos/<id>delete a todo with delete request to
/todos/<id>
Deploying the API
Now it's time to deploy the API, so first we have setup to do...
install the libraries we need...
pip install django-heroku gunicorn django-cors-headersgunicorn: web server to run in production
django-heroku: configures our app for heroku deployment
django-cors-headers: will be used to handle cors
If you have any issues with installing psychopg2 (django-heroku dep), it is either cause you don't have x-code installed on mac or on linux you need to install "libpq-dev", on ubuntu based systems the command would be
sudo apt-get install libpq-dev
setting up django-heroku
In settings.py
at the top import django-heroku
import django_herokuat the bottom add
django_heroku.settings(locals())
setting up django-cors-headers
In settings.py
- install the django-cors-headers app
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'todos.apps.TodosConfig',
'rest_framework',
'corsheaders'
]
- add the cors middleware
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware', ## <---- add here
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
- after the middleware section add this line to allow all origins
CORS_ALLOW_ALL_ORIGINS = True ## <---- will allow all origins, read cors docs to limit
Additional Setup
- create a file called
Procfilein the root of your project (where manage.py is)
web: gunicorn todoproject.wsgi
- add a runtime.txt in the project root with your python version
python-3.9.0
- generate a list of dependencies in requirements.txt with the command
pip freeze > requirements.txtmake sure to redo this anytime you add new dependencies
Getting it to heroku
create a git repo in the root, commit, then push up to github.com repo
create a new heroku project, connect your git repo to it, deploy
run
python manage.py migratefrom the heroku dashboard or the heroku clitest you newly deployed api in postman.