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 Todofrom django.contrib.auth.models import User, Groupfrom rest_framework import serializers
# Our TodoSerializerclass 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 Todofrom rest_framework import viewsetsfrom rest_framework import permissionsfrom .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 adminfrom django.urls import path, includefrom rest_framework import routersfrom todos.views import TodoViewSet
# create a new routerrouter = routers.DefaultRouter()# register our viewsetsrouter.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 limitAdditional 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.