You are currently viewing Django Angular CRUD Example: Building Dynamic Interfaces with Django Rest Framework (DRF)

Django Angular CRUD Example: Building Dynamic Interfaces with Django Rest Framework (DRF)

Embark on a Comprehensive Full Stack Journey: Building a CRUD App with Django and Angular 16/15/14/13

In this instructive tutorial, we will delve into the art of crafting a dynamic full stack application. Join us as we seamlessly integrate Django, powered by Python 3, alongside the versatile Django Rest Framework for robust REST APIs. On the frontend, we embrace the power of Angular 16/15/14/13, skillfully wielding tools like HttpClient and Router to create an engaging user interface. Prepare to unlock a world of possibilities as we guide you through the creation of a fully functional CRUD app, bridging the gap between the backend and frontend realms.

Django + Angular Integration: Comprehensive Example Overview

Join us on a journey to construct a full-stack Django and Angular 16/15/14/13 Tutorial Application, where:

  • Every Tutorial is enriched with a unique id, a captivating title, a descriptive narrative, and a status indicating its publication.
  • We unlock the power to Create, Retrieve, Update, and Delete Tutorials, encompassing the full spectrum of CRUD operations.
  • The ability to seamlessly Discover Tutorials by their titles further enhances our application’s prowess.

Get ready to witness the fusion of Django’s backend elegance with Angular’s dynamic frontend, crafting a harmonious synergy that culminates in a robust and engaging Tutorial Application.

Architecture of Django Angular Tutorial example

– Django Server exports REST Apis using Django Rest Framework & interacts with Database using Django Model.
– Angular 16/15/14/13 Client sends HTTP Requests and retrieve HTTP Responses using HttpClient Module, shows data on the components. We also use Angular Router for navigating to pages.

Overview

These are APIs that Django App will export:

MethodsUrlsActions
POST/api/tutorialscreate new Tutorial
GET/api/tutorialsretrieve all Tutorials
GET/api/tutorials/:idretrieve a Tutorial by :id
PUT/api/tutorials/:idupdate a Tutorial by :id
DELETE/api/tutorials/:iddelete a Tutorial by :id
DELETE/api/tutorialsdelete all Tutorials
GET/api/tutorials?title=[keyword]find all Tutorials which title contains keyword

Technology

  • Python 3.7
  • Django 2.1.15
  • Django Rest Framework 3.11.0
  • PyMySQL 0.9.3 (MySQL) / psycopg2 2.8.5 (PostgreSQL) / djongo 1.3.1 (MongoDB)
  • django-cors-headers 3.2.1

Project Structure

This is our Django project structure:

image 1

– tutorials/apps.py: declares TutorialsConfig class (subclass of django.apps.AppConfig) that represents Rest CRUD Apis app and its configuration.
– RestApis/settings.py: contains settings for our Django project: Database engine, INSTALLED_APPS list with Django REST framework, Tutorials Application, CORS and MIDDLEWARE.
– tutorials/models.py: defines Tutorial data model class (subclass of django.db.models.Model).
– migrations/0001_initial.py: is created when we make migrations for the data model, and will be used for generating database table/collection.
– tutorials/serializers.py: manages serialization and deserialization with TutorialSerializer class (subclass of rest_framework.serializers.ModelSerializer).
– tutorials/views.py: contains functions to process HTTP requests and produce HTTP responses (using TutorialSerializer).
– tutorials/urls.py: defines URL patterns along with request functions in the Views.
– RestApis/urls.py: also has URL patterns that includes tutorials.urls, it is the root URL configurations.

Install Django REST framework

Django REST framework helps us to build RESTful Web Services flexibly.

To install this package, run command:
pip install djangorestframework

Setup new Django project

Let’s create a new Django project with command:
django-admin startproject bzkRestApis

When the process is done, you can see folder tree like this:

image 2

Now we open settings.py and add Django REST framework to the INSTALLED_APPS array here.

INSTALLED_APPS = [
    ...
    # Django REST framework 
    'rest_framework',
]

Setup Database engine

Open settings.py and change declaration of DATABASES:

DATABASES = {
    'default': {
        'ENGINE': ...,
        'NAME': '...',
        'USER': 'root',
        'PASSWORD': '123456',
        'HOST': '127.0.0.1',
        'PORT': ...,
    }
}

Setup new Django app for Rest CRUD Api

Run following commands to create new Django app tutorials:

cd RestApis
python manage.py startapp tutorials

Refresh the project directory tree, you can see it now looks like:

image 3

Now open tutorials/apps.py, you can see TutorialsConfig class (subclass of django.apps.AppConfig).
This represents the Django app that we’ve just created with its configuration:

from django.apps import AppConfig


class TutorialsConfig(AppConfig):
    name = 'tutorials'

Don’t forget to add this app to INSTALLED_APPS array in settings.py:

INSTALLED_APPS = [
    ...
    # Tutorials application 
    'tutorials.apps.TutorialsConfig',
]

Configure CORS

We need to allow requests to our Django application from other origins.
In this example, we’re gonna configure CORS to accept requests from localhost:8081.

First, install the django-cors-headers library:
pip install django-cors-headers

In settings.py, add configuration for CORS:

INSTALLED_APPS = [
    ...
    # CORS
    'corsheaders',
]

You also need to add a middleware class to listen in on responses:

MIDDLEWARE = [
    ...
    # CORS
    'corsheaders.middleware.CorsMiddleware',
    'django.middleware.common.CommonMiddleware',
]

Note: CorsMiddleware should be placed as high as possible, especially before any middleware that can generate responses such as CommonMiddleware.

Next, set CORS_ORIGIN_ALLOW_ALL and add the host to CORS_ORIGIN_WHITELIST:

CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
    'http://localhost:8081',
)
  • CORS_ORIGIN_ALLOW_ALL: If True, all origins will be accepted (not use the whitelist below). Defaults to False.
  • CORS_ORIGIN_WHITELIST: List of origins that are authorized to make cross-site HTTP requests. Defaults to [].

Define the Django Model

Open tutorials/models.py, add Tutorial class as subclass of django.db.models.Model.
There are 3 fields: titledescriptionpublished.

from django.db import models


class Tutorial(models.Model):
    title = models.CharField(max_length=70, blank=False, default='')
    description = models.CharField(max_length=200,blank=False, default='')
    published = models.BooleanField(default=False)

Each field is specified as a class attribute, and each attribute maps to a database column.
id field is added automatically.

Migrate Data Model to the database

Run the Python script: python manage.py makemigrations tutorials.

The console will show:

Migrations for 'tutorials':
  tutorials\migrations\0001_initial.py
    - Create model Tutorial

Refresh the workspace, you can see new file tutorials/migrations/0001_initial.py.
It includes code to create Tutorial data model:

# Generated by Django 2.1.15

from django.db import migrations, models


class Migration(migrations.Migration):

    initial = True

    dependencies = [
    ]

    operations = [
        migrations.CreateModel(
            name='Tutorial',
            fields=[
                ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('title', models.CharField(default='', max_length=70)),
                ('description', models.CharField(default='', max_length=200)),
                ('published', models.BooleanField(default=False)),
            ],
        ),
    ]

The generated code defines Migration class (subclass of the django.db.migrations.Migration).
It has operations array that contains operation for creating Tutorial model table: migrations.CreateModel().

The call to this will create a new model in the project history and a corresponding table in the database to match it.

To apply the generated migration above, run the following Python script:
python manage.py migrate tutorials

The console will show:

Operations to perform:
  Apply all migrations: tutorials
Running migrations:
  Applying tutorials.0001_initial... OK

At this time, you can see that a table/collection for Tutorial model was generated automatically with the name: tutorials_tutorial in the database.

Create Serializer class for Data Model

Let’s create TutorialSerializer class that will manage serialization and deserialization from JSON.

It inherit from rest_framework.serializers.ModelSerializer superclass which automatically populates a set of fields and default validators. We need to specify the model class here.

tutorials/serializers.py

from rest_framework import serializers 
from tutorials.models import Tutorial
 
 
class TutorialSerializer(serializers.ModelSerializer):
 
    class Meta:
        model = Tutorial
        fields = ('id',
                  'title',
                  'description',
                  'published')

In the inner class Meta, we declare 2 attributes:

  • model: the model for Serializer
  • fields: a tuple of field names to be included in the serialization

Define Routes to Views functions

When a client sends request for an endpoint using HTTP request (GET, POST, PUT, DELETE), we need to determine how the server will response by defining the routes.

These are our routes:

  • /api/tutorials: GET, POST, DELETE
  • /api/tutorials/:id: GET, PUT, DELETE
  • /api/tutorials/published: GET

Create a urls.py inside tutorials app with urlpatterns containing urls to be matched with request functions in the views.py:

from django.conf.urls import url 
from tutorials import views 
 
urlpatterns = [ 
    url(r'^api/tutorials$', views.tutorial_list),
    url(r'^api/tutorials/(?P<pk>[0-9]+)$', views.tutorial_detail),
    url(r'^api/tutorials/published$', views.tutorial_list_published)
]

Don’t forget to include this URL patterns in root URL configurations.
Open bzkRestApis/urls.py and modify the content with the following code:

from django.conf.urls import url, include 
 
urlpatterns = [ 
    url(r'^', include('tutorials.urls')),
]

Write API Views

We’re gonna create these API functions for CRUD Operations:
– tutorial_list(): GET list of tutorials, POST a new tutorial, DELETE all tutorials
– tutorial_detail(): GET / PUT / DELETE tutorial by ‘id’
– tutorial_list_published(): GET all published tutorials

Open tutorials/views.py and write following code:

from django.shortcuts import render
...

@api_view(['GET', 'POST', 'DELETE'])
def tutorial_list(request):
    # GET list of tutorials, POST a new tutorial, DELETE all tutorials
 
 
@api_view(['GET', 'PUT', 'DELETE'])
def tutorial_detail(request, pk):
    # find tutorial by pk (id)
    try: 
        tutorial = Tutorial.objects.get(pk=pk) 
    except Tutorial.DoesNotExist: 
        return JsonResponse({'message': 'The tutorial does not exist'}, status=status.HTTP_404_NOT_FOUND) 
 
    # GET / PUT / DELETE tutorial
    
        
@api_view(['GET'])
def tutorial_list_published(request):
    # GET all published tutorials

Run the Django Rest Api Server

Run our Django Project with command: python manage.py runserver 8080.
The console shows:

Performing system checks...

System check identified no issues (0 silenced).
Django version 2.1.15, using settings 'RestApis.settings'
Starting development server at http://127.0.0.1:8080/
Quit the server with CTRL-BREAK.

Angular Frontend

– The App component is a container with router-outlet. It has navbar that links to routes paths via routerLink.

– TutorialsList component gets and displays Tutorials.
– TutorialDetails component has form for editing Tutorial’s details based on :id.
– AddTutorial component has form for submission new Tutorial.

– These Components call TutorialService methods which use Angular HTTPClient to make HTTP requests and receive responses.

Technology

  • Angular 16/15/14/13
  • Angular HttpClient
  • Angular Router
  • Bootstrap 4
image 4

– tutorial.model.ts exports the main class model: Tutorial.
– There are 3 components: tutorials-listtutorial-detailsadd-tutorial.
– tutorial.service has methods for sending HTTP requests to the Apis.
– app-routing.module.ts defines routes for each component.
– app component contains router view and navigation bar.
– app.module.ts declares Angular components and import necessary modules.

Setup Angular Project

Let’s open cmd and use Angular CLI to create a new Angular Project as following command:

ng new angular-16-crud
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? CSS

We also need to generate some Components and Services:

ng g s services/tutorial

ng g c components/add-tutorial
ng g c components/tutorial-details
ng g c components/tutorials-list

ng g class models/tutorial --type=model

Set up App Module

Open app.module.ts and import FormsModuleHttpClientModule:

...
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http';

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

Define Routes for Angular AppRoutingModule

There are 3 main routes:
– /tutorials for tutorials-list component
– /tutorials/:id for tutorial-details component
– /add for add-tutorial component

app-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { TutorialsListComponent } from './components/tutorials-list/tutorials-list.component';
import { TutorialDetailsComponent } from './components/tutorial-details/tutorial-details.component';
import { AddTutorialComponent } from './components/add-tutorial/add-tutorial.component';

const routes: Routes = [
  { path: '', redirectTo: 'tutorials', pathMatch: 'full' },
  { path: 'tutorials', component: TutorialsListComponent },
  { path: 'tutorials/:id', component: TutorialDetailsComponent },
  { path: 'add', component: AddTutorialComponent }
];

@NgModule({
  imports: [RouterModule.forRoot(routes)],
  exports: [RouterModule]
})
export class AppRoutingModule { }

Define Model Class

Our main model class Tutorial will be exported in tutorial.model.ts with 4 fields:

  • id
  • title
  • description
  • published

models/tutorial.model.ts

export class Tutorial {
  id?: any;
  title?: string;
  description?: string;
  published?: boolean;
}

Create Data Service

This service will use Angular HttpClient to send HTTP requests.
You can see that its functions includes CRUD operations and finder method.

services/tutorial.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Tutorial } from '../models/tutorial.model';

const baseUrl = 'http://localhost:8080/api/tutorials';

@Injectable({
  providedIn: 'root'
})
export class TutorialService {

  constructor(private http: HttpClient) { }

  getAll(): Observable<Tutorial[]> {
    return this.http.get<Tutorial[]>(baseUrl);
  }

  get(id: any): Observable<Tutorial> {
    return this.http.get(`${baseUrl}/${id}`);
  }

  create(data: any): Observable<any> {
    return this.http.post(baseUrl, data);
  }

  update(id: any, data: any): Observable<any> {
    return this.http.put(`${baseUrl}/${id}`, data);
  }

  delete(id: any): Observable<any> {
    return this.http.delete(`${baseUrl}/${id}`);
  }

  deleteAll(): Observable<any> {
    return this.http.delete(baseUrl);
  }

  findByTitle(title: any): Observable<Tutorial[]> {
    return this.http.get<Tutorial[]>(`${baseUrl}?title=${title}`);
  }
}

Create Angular Components

As you’ve known before, there are 3 components corresponding to 3 routes defined in AppRoutingModule.

  • Add new Item Component
  • List of items Component
  • Item details Component

Run the Angular App

You can run this App with command: ng serve --port 8081.
If the process is successful, open Browser with Url: http://localhost:8081/ and check it.

Leave a Reply