Building a Web App with Angular, Django and Django REST

18 months ago i posted the following post about integrating Angular and Django. Meanwhile, we have new releases and some updates.

Angular 7 is one of the best javascript frameworks. With typescript as a regular programming language , its separation of data and views,  CSS and HTML, its finally feels like real programming on client side.

You can build the server side using many technologies: nodejs if you want to javascript also on the server, ASP.NET if you want microsoft on your back and many more

I prefer python. Its easy, dynamic , has tons of packages available and integrates with all kind of data – local, cloud, small and big

Python offers many frameworks to build a web application – I prefer Django

In this post, I will build a simple web application using:

I also use jetbrains tools : Webstorm for client side and pycharm for the server side, Using these tools, you can open an Angular cli project and django project and skip the basic setup steps

The server – Django and Django REST 

I will go over the steps and also post the result:

  • create an empty folder
  • create and activate a virtual environmemt:
# python -m venv venv

# source venv/bin/activate
  • install Django
# pip install django
  • create the app
# django-admin startproject datatest

# python manage.py startapp data
  • Add migration so you can change your database schema easily:
# python manage.py migrate
  • Run the server to see the first app:
# python manage.py runserver

You can now open your web browser and go to http://localhost:8000 to see its working.

  • Install the following packages using pip
# pip install gunicorn
# pip install dj-database-url
# pip install whitenoise
# pip install psycopg2-binary
# pip install djangorestframework

 

Client Side – Angular 7

  • Install node.js – LTS 
  • Install Angular cli
# npm install -g @angular/cli
  • Create a new Angular project
# ng new testapp
  • Test it using local server:
# ng serve
  • Build the project
# ng build

This will create dist folder with everything you need for deploying the client side

Integrating with Django project:

  • Copy the js files (including the map files) to the static folder on your Django project (data/static)
  • Copy index.html generated by angular project to the templates folder – override the existing one (data/templates)
  • Change the index.html file as follow:
{% load static %}
<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <title>Home</title>
  <base href="/">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
      <!-- index.html -->
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
  <app-root>Loading...</app-root>
  <script type="text/javascript" src="{% static 'es2015-polyfills.js' %}"></script>
  <script type="text/javascript" src="{% static 'polyfills.js' %}"></script>
  <script type="text/javascript" src="{% static 'styles.js' %}"></script>
  <script type="text/javascript" src="{% static 'vendor.js' %}"></script>
  <script type="text/javascript" src="{% static 'runtime.js' %}"></script>
  <script type="text/javascript" src="{% static 'main.js' %}"></script></body>
</html>

 

Update the settings.py file

On the django project we need to make some settings to enable the static folder and the REST framework

Add the rest framework to the installed apps:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'data.apps.DataConfig',
    'rest_framework',
]

 

Update the middleware:

MIDDLEWARE = [
    'whitenoise.middleware.WhiteNoiseMiddleware',
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

Set the static folder – add the following at the bottom of the settings file:

import dj_database_url
db_from_env = dj_database_url.config(conn_max_age=500)
DATABASES['default'].update(db_from_env)


PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
STATIC_ROOT = os.path.join(PROJECT_ROOT, 'staticfiles')
STATIC_URL = '/static/'

# Extra places for collectstatic to find static files.
STATICFILES_DIRS = (
    os.path.join(PROJECT_ROOT, 'static'),
)

# Simplified static file serving.
# https://warehouse.python.org/project/whitenoise/

STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'

 

Add some views and REST API – Server

  • Add new entry to urls.py at the main project folder (datatest):
from django.conf.urls import url
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    url(r'^', include('data.urls'))
]
  • Add file urls.py to the App folder (data). Set a router for customers REST API, add 2 simple views and one api entry
from django.conf.urls import url
from django.urls import path, include

from data import views
from rest_framework import routers


router = routers.DefaultRouter()
router.register(r'customers', views.CustViewSet)

urlpatterns = [
    url(r'^$', views.HomePageView.as_view()),
    url(r'^links/$', views.LinksPageView.as_view()), # simple view
    url(r'^getcust/$',views.Customers.getCust), # simple view
    url(r'^apitest/$',views.CalcTest), # for REST API test
]
  • Create a templates folder on the module folder(first) and add your html files (index.html, links.html)
  • On the views.py file add the following class:
from django.http import HttpResponse, JsonResponse
from django.shortcuts import render
from django.views.generic import TemplateView


# Create your views here.
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.utils import json
from rest_framework import serializers
from rest_framework import viewsets

from data.models import Customer


class HomePageView(TemplateView):
    def get(self, request, **kwargs):
        return render(request, 'index.html', context=None)


class LinksPageView(TemplateView):
    def get(self, request, **kwargs):
        return render(request, 'links.html', context=None)

class Customers(TemplateView):
    def getCust(request):
        name='liran'
        return HttpResponse('{ "name":"' + name + '", "age":31, "city":"New York" }')

 

Django REST Framework

To use Django REST framework we add a simple function to multiply the given argument by 100. Add the following code to the views.py file:

@api_view(["POST"])
def CalcTest(x1):
    try:
        x=json.loads(x1.body)
        y=str(x*100)
        return JsonResponse("Result:"+y,safe=False)
    except ValueError as e:
        return Response(e.args[0],status.HTTP_400_BAD_REQUEST)

Now , the server side is ready, you can run the server and test the different views. You can’t test the REST API using the browser because it doesn’t support GET method (only POST)

 

Angular Client Code

To test the server functionality , we will build a simple view

To use http requests from angular, we need to add the HttpClient service class (instead of http module that is deprecated)

app.module.ts file

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';
import { BooksComponent } from './books/books.component';

@NgModule({
  declarations: [
    AppComponent,
    BooksComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Now we can add some code to use the server views and API

app.component.ts

import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'djint';
  constructor(private _http:HttpClient) {
    this.c1.name = "eli"
  }

  c1:Cust = new Cust();
  click1(){
    this.getBooks().subscribe(b => this.c1.name = b.toString())
  }
  click2(){
    this.getAllBooks().subscribe(b => this.c1 = b)
  }

  getAllBooks()
  {
    return this._http
      .get<Cust>("./getcust") // GET request  
  }
  getBooks()
  {
    return this._http
      .post("./apitest/","5") // POST request with argument
  }
}

export class Cust{
  name:string;
  age:number;
  city:string;
}

The first function create a get request and the second creates a post request. This is a simple example to build only the skeleton 

app.component.html

<div style="text-align:center">
  <h1>
    Welcome to {{ title }}!
  </h1>
  <h2>Test App: {{c1.name}}</h2>
  <button (click)="click1()" >click me</button>
  <button (click)="click2()" >click me</button>


</div>

Now its all set. to test the code run build and copy the js files to the static folder:

# ng build
# cp dist/djint/*.js ~/projects/datatest/data/static/
# cp dist/djint/*.js.map ~/projects/datatest/data/static/

Each time you change the client code, you need to repeat the build and copy process

To Download the complete code for both Angular and Django see this github repo

 

Want more?

 

 

 

Tagged , ,

14 thoughts on “Building a Web App with Angular, Django and Django REST

  1. Hi and thank you for this introduction to Angular, Django and Django REST. I’m a noob on Django/Django REST and convention escapes me (like folder structure). Could you post your final folder structure here so I can compare my interpretation of the instructions?

    1. NVM. I found it on your GitHub:
      https://github.com/dev-area/DjangoAngular7

      Thanks!

    2. nvm, I found it on your GitHub! Thanks again.
      https://github.com/dev-area/DjangoAngular7

  2. Nice but incomplete.
    It is not working “out of the box”

    1. Hi SHLOMO, were you able to create/find a build that was working “out of the box”?
      If so, please share! Or explain how to get it to a working state 🙂

  3. Thanks..works awesome…

  4. Autolike, auto liker, auto like, Photo Liker, Autoliker, Auto Like, Auto Liker, Increase Likes, Status Liker, ZFN Liker, Working Auto Liker, Autoliker, autolike, Photo Auto Liker, autoliker, Status Auto Liker, Autolike International

  5. This article is very helpful! Thank you soooooooo much!!!!

  6. Hi,
    I have created a small django-angular application with separate django server and angular server frontend.
    Now i have to build and deploy my application onto the server. I am going to follow devarea link to build and then deploy the application. Pls help me if i face some problems.

  7. Hi, I have created a website using Angular, and I am trying to integrate Django into this Angular project.

    In your example, you mentioned copying *.js and *.js.map from dist/djint folder, but in my project, there is no such folder. Inside dist folder, only server folder exists. So, even if I followed your example, I get 404 response because there is no main.js / runtime.js / etc. in static folder. So, where can I find those *.js and *.js.map files? What do I have to do to get all those files?

  8. Can Anyone help me with this
    When I am reloading my page or hit any route other then / it gives me page not found error.
    Actually I got to know when i am traversing through my application it uses our angular app router-outlet
    but if i hit url directly it is giving me page not found error it is trying to find that route in django urls. Can anyone tell me how to manage this

Comments are closed.