Building a Simple Website with Angular 4 and Django (and deploy it to heroku)

There are many alternatives to build a site , you need to select a client framework , a server platform, a database server and many other building blocks to help you link everything , develop, debug and deploy

One great option for server side development is python. With its huge number of packages and tools , python became a great programming language for desktop, server and web applications. Connecting to a database server? manipulating data? doing image and signal processing? writing a face recognition cloud based app? python will help you do these and much more in a very easy way with just few lines of code. For web development you can find many frameworks, the most popular is django

When you need to choose a client side framework its easier , first because we are using only one programming language – javascript and second because there are few options with clear differences. Most of the developers are using ReactJS or Angular. I prefer Angular

So i started to search how to create a site with Django on the server side and Angular 4 on client. I didn’t find a good working example, i had to make many changes but at the end i succeeded to create a site from scratch with:

  • Angular 4 on the client side
  • Django on the server side
  • All deployed to heroku

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

  • Install python 3
  • Install virtual environment:
# pip install virtualenv
  • create an empty folder
  • create and activate a virtual environmemt:
# virtualenv -p /usr/local/bin/python3 env

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

# python manage.py startapp first
  • Add the module name (first) to the installed apps (setting.py):
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'first',
]
  • 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.

Add some views to your app:

  • Add new entry to urls.py (urlpatterns):
url(r'^', include('first.urls'))
  • Add file urls.py to the App folder (first):
from django.conf.urls import url
from first import views

urlpatterns = [
    url(r'^$', views.HomePageView.as_view()),
    url(r'^links/$' , views.LinksPageView.as_view()),
]
  • 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.shortcuts import render
from django.views.generic import TemplateView

# Create your views here.
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)
  • Run the server again and see the results (try home page and /links address

Deploy the app to heroku

  • Create an heroku account
  • Create a Procfile on the root directory with this content:
web: gunicorn helloapp.wsgi --log-file –
  • Install the following packages:
# pip install gunicorn
# pip install dj-database-url
# pip install whitenoise
# pip install psycopg2
  • Add the following to the setting file (at the end):
# Update database configuration with $DATABASE_URL.
import dj_database_url
db_from_env = dj_database_url.config(conn_max_age=500)
DATABASES['default'].update(db_from_env)

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.9/howto/static-files/

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.django.GzipManifestStaticFilesStorage'

  • Add whitenoise to the middleware list of the settings file (the first line):
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',
]
  • Create a ‘static’ folder in helloapp folder
  • Save the installed packages:
# pip freeze > requirements.txt
  • login to heroku and create an application:
# heroku login
# heroku create [appname]
  • Add the appname to the ALLOWED_HOSTS in the settings file or put ‘*’ to allow any host:
ALLOWED_HOSTS = ['yourappname.herokuapp.com']

connect to your new app (or existing one):

# heroku git:remote -a [appname]
  • init a git repository
# git init

Create a .gitignore file:

venv
*.pyc
staticfiles
.env
  • push the project to the remote storage:
# git add .
# git commit -m "first"
# git push heroku master

Now go to the address appname.herokuapp.com and see the deployed website

  • To run heroku locally:
# heroku local web

 

Configuring Angular 4 as client side

  • Install node.js
  • 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 to the static folder on your Django project (helloapp/static)
  • Copy index.html generated by angular project to the templates folder – override the existing one (first/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 'inline.bundle.js' %}"></script>
<script type="text/javascript" src="{% static 'polyfills.bundle.js' %}"></script>
<script type="text/javascript" src="{% static 'styles.bundle.js' %}"></script>
<script type="text/javascript" src="{% static 'vendor.bundle.js' %}"></script>
<script type="text/javascript" src="{% static 'main.bundle.js' %}"></script></body>
</html>



note the use of static to tell Django to load the js files from the static folder (declared in settings.py)

  • Now you can generate and deploy
# git add .
# git commit -m "first"
# git push heroku master

Example – http request from Angular to Django

  • Define another view in views.py file:
class Customers(TemplateView):
    def getCust(request):
        name='liran'
        return HttpResponse('{ "name":"' + name + '", "age":31, "city":"New York" }')
  • Declare the new url in urls.py file
urlpatterns = [
    url(r'^$', views.HomePageView.as_view()),
    url(r'^links/$' , views.LinksPageView.as_view()),
    url(r'^getcust/$',views.Customers.getCust),
]
  • Test it using the local web ( http://127.0.0.1:8000/getcust ) – you need to see the json response

Http request from Angular:

  • Add the HttpModule to the app.module.ts file:
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpModule } from '@angular/http';

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

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }
  • On the button click event make the http request to the ‘getcust’ view
import { Component } from '@angular/core';
import {Http, Response} from '@angular/http';
import {Observable} from 'rxjs';
import 'rxjs/add/operator/map';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  constructor(private _http:Http) {
    this.c1.name = "eli"
   }
  title = 'app';
  c1:Cust = new Cust();
  click1(){
    this.getAllBooks().subscribe(b => this.c1 = b)
  }

  getAllBooks()
  {
    return this._http
          .get("./getcust")
          .map(r => <Cust>r.json())
  }
}

export class Cust{
    name:string;
    age:number;
    city:string;
}
  • Add binding to the html file:
<div style="text-align:center">
  <h1>
    Welcome to {{title}}!
  </h1>
  
</div>
<h2>Test App: {{c1.name}}</h2>
<button (click)="click1()" >click me</button>
  • build the client side
# ng build
  • Copy the js files to the static folder
  • Deploy the site again:
# git add .
# git commit -m "first"
# git push heroku master

you can find the complete code both server and client here

Thats All !!!

Next post i’ll integrate NumPy, Matplotlib and Pandas

Subscribe to our list

Loading
Tagged , ,

27 thoughts on “Building a Simple Website with Angular 4 and Django (and deploy it to heroku)

  1. […] For getting started tutorial for using both Angular and Django see this post […]

  2. I have completed the tutorial as instructed, apart from deploying, like i am currently developing using the local server. The problem is after completing the first http response now i again changed the app-component and my user components html and .ts files, then my angular server is working with the updated html, but after building from “ng build” and then copying .js files to static folder django is stuck with the older version, meaning its not using the updated angular html but rather using the old files,
    even i removed the files from static folder and from templates/index.html, still django works with the previos integrated angular.
    Don’t know whether it has saved the angular previously deployed somewhere and is using it every time or aomething else…

    Any help would be appreciated.
    Thank You.

    1. This happens because Django uses cache for static resources.
      look here for some solutions:
      https://stackoverflow.com/questions/7013735/turn-off-caching-of-static-files-in-django-development-server

  3. Thanks for the tutorial.
    I have only read it (not actually done it) but one point worries me: “copy the js files to the static folder”.
    Does it mean that every time we make client-side changes (Angular 4 changes), we need to manually build and copy the generated code?
    Is it possible to automate that both on the development server and on the deployed version?

    Thanks,
    Thomas

    1. sure
      you can customize the npm build script (ng build) to copy the generated files to the static folder

      1. Hi, do you have a reference link for this or steps on how we can customize the npm build script to copy the generated files to the static folder?

        1. I will add and post it here soon

        2. just change line 9 in .angular-cli.json into this:
          “outDir”: “../helloapp/helloapp/static”,

          great tutorial btw..
          thx!
          lou

    2. I know a bit late, but it might help someone, you can directly build to the static of your backend using ‘ng build –output-path /path/to/your/static –prod –watch –output-hashing none’

  4. Hi Liran,

    Facing issue while developing demo app with Django and Angular4. If you have, could you please share video link of the above steps.

    Regards,
    Sumit

  5. thank you very much
    this worked for me

  6. Hi, I have a question about the images url , like “”, and the back-end is Django, loging with django’s port(8000), it will reports :

    “Using the URLconf defined in django_angular.urls, Django tried these URL patterns, in this order:

    ^admin/
    The current URL, assets/imgs/sclogo.png, didn’t match any of these.”

    So is there some good solution for this? Thanks

  7. Hi Liran,

    I received the following error as I test url http://127.0.0.1:8000/getcust:
    “unbound method getCust() must be called with Customers instance as first argument (got WSGIRequest instance instead)”

    How could I fix this?

    By the way, thank you for this tutorial.

    1. Like the error message states: you need to call getCust() with a customers object (mycustomers.getCust())

      1. Hi,
        could you please develop this, I have the same problem as Felix and I don’t really understand your answer. In your example, you write return this._http.get(“./getcust”).map(r => r.json()). So where do you declare mycustomers, on django side or on angular side ?

        Thanks to clarify what i missed.

        Denis

        1. Add @classmethodabove the def in python 2 (not needed in python 3)

  8. hi,
    when i deploy my application on heroku..the app is crashed everytime.
    its shows gunicorn.errors.haltserver
    can you please help me?

    1. did you follow the above tutorial ? what exactly you see on the log?

      1. I am also stuck at the point where I push to heroku. Build is succeeded, but when it starts the process with command ‘gunicorn appname.wsgi –log-file -‘ it exits without a clear reason.
        In the logs I see ‘state changed from starting to crashed’ . On the line above it says it exits with status 127 (I am gonna google this now, hopefully I’ll find an anwser)

        1. OK, I did find something. And it works on my machine now. What helped for me, is to use the exact name for the directory (the django-project name) and the app on Heroku. You also fill in this name in the procfile, and then it magically stays up. I am not sure why, but maybe you know…..?

  9. I followed the tutorial and I have some feedback to get more people going with this very cool tutorial 🙂

    1. After changing ALLOWED_HOSTS , you should first do git init, and then after that, you connect to your heroku app.

    2. when you create a directory ‘static’, you should also place an empty file in this directory, so that heroku doesn’t skip it when pushed to the server….

    1. Also when you alter the first urls.py , you could add that you should import both urls and include from django.confs.url

    2. I found another improvement you could add to the tutorial:
      At the point where you are in chapter ‘Example – http request from Angular to Django’ , you should also import HttpResponse from django.http

  10. Hi i found your tutorial very helpful, but i am now trying to move on using css files and images. I’ve tried serving the assets folder from the angular project through django by placing it in the static folder but not everything is loaded. can you shed some light on this issue? thanks a lot.

  11. hi,
    First of all – a wonderful guide! Thank you very very much
    Second, the application did open to me on the computer, but on the mobile it does not work (only shows “loading”)

    any ideas?

  12. […] months ago i posted the following post about integrating Angular and Django. Meanwhile, we have new releases and some […]

  13. I used your tutorial and was able to make a Django app work with Angular 4. Thank you so much for this. Highly appreciate your effort to help others to be able to do this.

Comments are closed.