How to integrate Django REST Framework and Angular

How to integrate Django REST Framework and Angular

Whenever I need to start prototyping a modern web app for a client, Django (REST Framework) and Angular tend to be my tools of choice. Both are true frameworks, they are opinionated and come with the batteries included. Because Angular and Django provide all the scaffolding, I can spend my time writing business logic.

There’s lots of ways you can integrate these frameworks, but I’ll run you through how I setup my Django and Angular apps.

Hierarchy

First of all, let me clarify that whenever I’m referring to Django in this article, it’s really mostly Django REST Framework (DRF). Since Angular is typically my pretty front-end for the users, Django is nothing more than a back-end which is exposed through the REST Framework.

At first, I really wasn’t sure on how to structure my Django and Angular code to neatly live alongside each other.

  • Should the front-end (Angular) and back-end (Django) reside in entirely different Git repositories? That seemed a little convoluted for the “small” apps I’m developing and the two will be tightly integrated anyway.

  • Should I create two top-level directories, front-end and back-end at the root of my repository? It’s certainly an option I’ve seen in some open-source projects. But it’s ugly. And as I later found out, it really makes integration and deployment of the app harder.

  • Or should Django live at the root of the repository and the Angular front-end can go into a subdirectory?

For any new projects, I always go with that last option. As you’ll see further down, I actually create a Django app “frontend” where Angular lives. This way, Django can serve up the compiled Angular front-end during development and it can also collect the compiled version as static content and i.e. place it in a CDN.

So to get started I’ll do something like this:

mkdir djangular
cd djangular/
virtualenv env
source env/bin/activate
pip install django
pip install djangorestframework
django-admin startproject djangular .
python manage.py startapp heroes
python manage.py startapp api
python manage.py startapp frontend
ng new djangular --directory=./frontend/

Some Git housekeeping

Then I’ll create the README.md and a .gitignore which will tell Git to ignore a couple of folders from source control.

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
# Distribution / packaging
/static/*
!/static/.gitkeep
# IDEs
.vscode/
# Virtual environement
/env/
# SQLite
db.sqlite3

Note: the .vscode/ and /env/ directories are related to my code editor (Visual Studio Code) and Python Virtual Enviornment and may not be relevant to you.

The new Angular app has initialized a new Git repository in frontend/. As I’d like to keep a single Git repository I’ll remove that .git sub directory:

rm -rf frontend/.git/

The new Angular app has also created a frontend/.gitignore file which has a bunch of sane defaults in it. I’ll just change the dist/ to static/ in there which is the folder I’ll use to output my Angular builds.

Now I can initialize my Git repository and do a first commit.

git init .
git add .
git commit -m "Initial commit"

Do a first Angular build

By default Angular will build in dist/djangular as defined by the outputPath setting in angular.json. So I’m just going to change it to static/frontend to align with Django’s expectations.

As always with a standard Django setup, static files will be hosted under /static/<app>. So I’ll need to tell Angular to go look for all its assets there as well. I’ll start a build with ng build --deploy-url=/static/frontend/ and get the Angular hello world app.

Django setup

Next, I’m fixing up my Django djangular/settings.py to load the REST framework and my frontend and heroes apps. There’s no need to add in the api app as I’m really only using it to split out the URLs.

INSTALLED_APPS = [
    ...
    'rest_framework',
    'frontend.apps.FrontendConfig',
    'heroes.apps.HeroesConfig',
]

I’ll also want to tell Django to get all my static files for the frontend by modifying the ‘DIRS’ setting under the TEMPLATES.

TEMPLATES = [
    {
        ...
        'DIRS': [os.path.join(BASE_DIR, 'frontend/static/')],

The djangular/urls.py gets the following content:

from django.contrib import admin
from django.urls import include, path, re_path
from frontend import views as frontend_views
urlpatterns = [
    path('api/v1/', include('api.urls')),
    path('admin/', admin.site.urls),
    re_path(r'^(?P<path>.*)/$', frontend_views.index),
    path('', frontend_views.index),
]

So all my API endpoints reside under /api/v1/, the Django admin resides under ‘/admin/’. Everything else is redirected into the frontend view.

That frontend view in frontend/views.py is actually really simple and loads the index.html that Angular has created for us.

from django.shortcuts import render

def index(request, path=None):
    return render(request, 'frontend/index.html')

The api/urls.py is pretty simple as well and just includes the Model View Set for my Hero model. The ViewSet itself and its Serializer and Model are all pretty standard Django REST Framework and you can check those out in the Git repository.

I’ll now make my migrations, run them and setup a superuser. Finally, I’ll start the development server.

Testing the API

If everything goes to plan, I should now be able to start my Django development server and:

  • View the default Angular splash page at http://localhost:8000

  • Access the admin at http://localhost:8000/admin/ and add in a few heroes

  • Retrieve my heroes with the API at http://localhost:8000/api/v1/heroes/

Retrieve the heroes from Angular

Finally, I’d like to have my heroes retrieved from the backend and displayed in the Angular app. You can go check out the basic components and services I’ve setup to do that in the Git repository.

More information

If you are following along, you should check out the repository on GitHub that accompanies this post.

How to configure CUCM via the AXL SOAP API with Python

How to configure CUCM via the AXL SOAP API with Python