Django is a Python-based free and open-source web framework that follows the model-template-view architectural pattern. Angular 9 is a TypeScript-based open-source web application framework led by the Angular Team at Google. In the tutorial, I introduce how to build a “Django Python Angular 9 PostgreSQL CRUD RestAPI Example” with Fullstack Projects providing POST/GET/PUT/DELETE requests using Django Rest Framework and PostgreSQL database with step by step coding examples:
– I draw a fullstack overview Diagram Architecture from Angular 9 Frontend to PostgreSQL database through Django RestAPI backend.
– Develop Django CRUD RestAPIs with the supporting of Django Rest Framework.
– Implement Angular 9 CRUD application with the Angular 9 Httpclient to do CRUD request (Post/Get/Put/Delete) to Django Backend APIs.
– I create a testsuite with a number of integrative testcases with CRUD RestAPI requests from Angular 9 HttpClient to do CRUD requests to Django RestAPIs Server and save/retrieve data to PostgreSQL database.
- Overview Example – How to build “Django Python Angular 9 PostgreSQL CRUD RestAPI Example”?
- Django PostgreSQL RestAPIs CRUD Examples with Django Rest Framework
- Create a Django project
- Create a Django Application
- Create a Django Data model
- Serialize Data Model
- Setup PostgreSQL Database Configuration
- Migrate Data Model to PostgreSQL
- Configure Django Admin Page
- Testing Django Admin Page
- Implement Django CRUD Views – Post/Get/Put/Delete requests
- Configure Django CRUD RestAPI URLs
- Integrative Testing – Django + PostgreSQL CRUD RestAPIs
- Angular 9 CRUD Application Example – Frontend Development
- Angular 9 CRUD Application Overview with Django RestAPIs
- Create Angular 9 Application
- Create Angular 9 Typescript Model
- Create Typescript Message
- Implement Angular 9 CRUD HttpClient Service
- Implement Angular 9 post/get/put/delete components
- Configure Angular 9 Routing Module
- Modify Index.html View Page
- Integrative Testing: Angular 9 Application with Django CRUD RestAPIs + PostgreSQL
- Sourcecode
Overview Example – How to build “Django Python Angular 9 PostgreSQL CRUD RestAPI Example”?
Overall Diagram Architecture System: Angular 9 + Django + PostgreSQL
Here is an overview of Diagram Architecture Design for Django Angular 9 CRUD Example with Django Rest Framework and PostgreSQL:

- We build the backend Python Django Application that provides RestAPIs for POST/GET/PUT/DELETE data entities and store them in PostgreSQL database.
- We implement the Angular CRUD Application that uses Angular 9 HTTPClient to interact (call/receive requests) with Django backend’s CRUD RestAPIs and display corresponding page views in Browser
Django CRUD RestAPIs Design Application
- Django CRUD Application interacts with PostgreSQL database via Model layers.
- The Views are simply Python functions that take web requests and return web responses.
- URLs are used to mapping each request with the corresponding views.

Here is a Django CRUD RestAPIs project structure:

The project includes 2 folders:
djangoLoiZenAiRestAPIs
is a main project foldercustomers
is an application folder
Angular 9 HttpClient CRUD Diagram Application

Angular 9 CRUD Application is designed with 3 main layers:
- Service Layer is used to define Angular Common Services and HttpClient Services to interact with RestAPIs
- Component Layer is used to define Angular Components to show views in Browser for interacting with Users
- Router Layer is used to route URLs mapping with the corresponding Angular Components
Here is the Angular project structure:

Angular CRUD Application defines 3 components, 2 services, 1 routers, and 2 data models:
– Components:
add-customer
component is used to post a new customer entity to PostgreSQL through Django RestAPIslist-customer
component is used to show all customer’s entities on view pages, delete a customer and update a customermessage
component is used to define a view to show logging message on browser
– Services:
customer.service.ts
defines CRUD Post/Get/Put/Delete http requests to Django RestAPIs with the built-in Angular HttpClient.message.service.ts
defines an array storage to log all messages when Angular CRUD Application running
– Router: app-routing.module.ts
defines how to map a corresponding Angular component with an URL.
– Models:
customer.ts
defines the main data model of our application.message.ts
defines the response data model between Django RestAPIs and Angular application.
Project Goal
Here is a list of goals for “Angular 9 Django PostgreSQL CRUD RestAPIs example” with Django Rest Framework:
– Angular client post a data to PostgreSQL database through Django RestAPI:

– List all PostgreSQL records:

– Get details of a Customer:

– Update a Customer:

– Delete a Customer:

Django PostgreSQL RestAPIs CRUD Examples with Django Rest Framework
Create a Django project
- In Django, every web application you want to create is called a project
- And a project is a sum of applications.
- An application is a set of code files relying on the MVT pattern.
– Open a cmd and type the below command to create a djangoLoiZenAiRestAPIs
project:
$ django-admin startproject djangoLoiZenAiRestAPIs
Now the project folder djangoLoiZenAiRestAPIs
is created with the following structure:
djangoLoiZenAiRestAPIs/
manage.py
djangoLoiZenAiRestAPIs/
__init__.py
settings.py
urls.py
wsgi.py
manage.py
is used to interact with your project via command line (start the development server, sync db…).__init__.py
is a python file that treats this folder as package.settings.py
is a project settings file.urls.py
defines all url links of your project and the function to callwsgi.py
is used when you deploy your project over WSGI
All setting of the Django project is in file djangoLoiZenAiRestAPIs/settings.py
.
Check a debug option:
DEBUG = True
This option sets your project is in debug mode or not. Debug mode gives you more information about your project’s error. In the production live build, Never set it to ‘True’.
Install Django REST framework
Django REST framework works on top of Django and helps us to build RESTful Web Services flexibly. To install this package, run command:
pip install djangorestframework
Create a Django Application
As mention in above session, a Django project has a set of many applications. Each application is implemented with a specific purpose and can be reused into another project.
For creating a Customer
application, we go to the project folder djangoLoiZenAiRestAPIs
. Start the cmd:
$ python manage.py startapp customers
Django will create a “customers” folder with the application structure as below:
customers/
__init__.py
admin.py
models.py
tests.py
views.py
__init__.py
is used by python to handle this folder as a package.admin.py
is used to hepl us modify the app in the admin interface.models.py
is place to store all application models.tests.py
is a place to write unit tests.views.py
is where to implement application views.
Open customers/apps.py
, we can see CustomersConfig
class (subclass of the django.apps.AppConfig
) that represents our Django app and its configuration:
from django.apps import AppConfig
class CustomersConfig(AppConfig):
name = 'customers'
We need to register our customes
application with our Django project djangoLoiZenAiRestAPIs
by updating INSTALLED_APPS
tuple in the settings.py
file of Django project:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Django REST framework
'rest_framework',
# Customers application
'customers.apps.CustomersConfig',
]
Create a Django Data model
A model class represents table or collection in our DB. Models are defined in the customers/models.py
:
from django.db import models
class Customer(models.Model):
firstname = models.CharField(max_length=70, blank=False, default='')
lastname = models.CharField(max_length=70, blank=False, default='')
age = models.IntegerField(blank=False, default=1)
address = models.CharField(max_length=70, blank=False, default='')
copyrightby = models.CharField(max_length=70, blank=False, default='')
All Django models must inherit from django.db.models.Model
. Customer
class has 5 attributes (4 CharField
and 1 Integer
), those will be the table fields.
Serialize Data Model
For serialization Python model object to JSON and deserialization Python object from JSON, We create a Serializer class for Customer instances:
– The CustomerSerializer
class will inherit from rest_framework.serializers.ModelSerializer
superclass.
– ModelSerializer
class automatically populates a set of default fields and default validators, we only need to specify the model class.
Now, under customers package, create serializers.py
file:
from rest_framework import serializers
from customers.models import Customer
class CustomerSerializer(serializers.ModelSerializer):
class Meta:
model = Customer
fields = ('id',
'firstname',
'lastname',
'age',
'address',
'copyrightby')
Meta inner class declares 2 attributes:
model
specifies the model related to the serializerfields
specifies a tuple of field names that we want to include in the serialization
Setup PostgreSQL Database Configuration
We use psycopg2
for Django interact with PostgreSQL database: pip install psycopg2
– Configure again the database tuple in settings.py
file:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'loizenjavadb',
'USER': 'root',
'PASSWORD': '12345',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}
Migrate Data Model to PostgreSQL
Run following Python script:
python manage.py makemigrations customers
We can see output text:
Migrations for 'customers':
customers\migrations\0001_initial.py
- Create model Customer
It indicates that the customers/migrations/0001_initial.py
file includes code to create Customer
data model:
# Generated by Django 3.0.8 on 2020-07-15 15:43
from django.db import migrations, models
class Migration(migrations.Migration):
initial = True
dependencies = [
]
operations = [
migrations.CreateModel(
name='Customer',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('firstname', models.CharField(default='', max_length=70)),
('lastname', models.CharField(default='', max_length=70)),
('age', models.IntegerField(default=1)),
('address', models.CharField(default='', max_length=70)),
('copyrightby', models.CharField(default='', max_length=70)),
],
),
]
The generated code defines a subclass of the django.db.migrations.Migration
. It has an operation for creating Customer
model table. Call to migrations.CreateModel()
method will create a table that allows the underlying database to persist the model.
Run the following Python script to apply the generated migration:
python manage.py migrate customers
The output text:
Operations to perform:
Apply all migrations: customers
Running migrations:
Applying customers.0001_initial... OK
Check PostgreSQL database, now we can see that a table for Customer
model was generated and it’s named customers_customer
:

Configure Django Admin Page
Django provides a ready-to-use user interface for administrative activities. To have it working you need to make sure some modules are imported in the INSTALLED_APPS
and MIDDLEWARE_CLASSES
tuples of the djangoLoiZenAiRestAPIs/settings.py
file.
– INSTALLED_APPS
make sure you have:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Django REST framework
'rest_framework',
# Customers application
'customers.apps.CustomersConfig',
# CORSq
'corsheaders',
]
– MIDDLEWARE_CLASSES:
MIDDLEWARE = [
'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',
# CORS
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
]
Before running Django server to access the Admin page, we need to initiate the database:
$ python manage.py migrate
Check PostgreSQL database tables:

Use the below command to create a super-user to login Admin page:
$ python manage.py createsuperuser
Register admin URL in djangoLoiZenAiRestAPIs/urls.py
file:
from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include
urlpatterns = [
path('admin/', admin.site.urls),
]
Register Customer
model in ./customers/admin.py
file:
from django.contrib import admin
# Register your models here.
from customers.models import Customer
# Register your models here.
admin.site.register(Customer)
Testing Django Admin Page
Launch Django server by cmd:
python manage.py runserver
Go to Admin page by URL link http://localhost:8000/admin/
:

Site Administration has 2 parts:
- AUTHENTICATION AND AUTHORIZATION
- CUSTOMERS
– Authentication and Authorization has Groups
and Users
pages, where we can add, modify, delete, update a specific user.

– Customers is a place to manipulate (create, get, update, delete) all entities of the Customers application.


Implement Django CRUD Views – Post/Get/Put/Delete requests
Django “view” is simply a Python function that takes a web request and returns a web response. This response can be the HTML contents of a Web page, or a redirect, or a 404 error, or an XML document, or an image … In the tutorial, we implement Django views that return JSON responses.

We create 2 Python function for Django views:
def customer_list(request)
is used to POST a Customer entity and GET all Customer entities per a request- def customer_detail(request, pk) is used to PUT/DELETE a Customer via id key
Django POST request
In the ./customers/views.py
customer_list(request) for POST/GET Customer entities:
@api_view(['GET', 'POST'])
def customer_list(request)
Here is a list of 4 steps we do to handle a Django POST request:
- Parsing a body request then serializing it to transform the JSON data to a Python Object
customer_data = JSONParser().parse(request) customer_serializer = CustomerSerializer(data=customer_data)
- Save the serializing object to database:
customer_serializer.save()
- Return a JsonResponse object to a client with a status code
JsonResponse(response, status=status.HTTP_201_CREATED)
- If having any error or exception, return the JSON error object to client
JsonResponse(error, status=status.HTTP_400_BAD_REQUEST) or JsonResponse(exceptionError, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
– Coding Example:
if request.method == 'POST':
try:
customer_data = JSONParser().parse(request)
customer_serializer = CustomerSerializer(data=customer_data)
if customer_serializer.is_valid():
customer_serializer.save()
print(customer_serializer.data)
response = {
'message': "Successfully Upload a Customer with id = %d" % customer_serializer.data.get('id'),
'customers': [customer_serializer.data],
'error': ""
}
return JsonResponse(response, status=status.HTTP_201_CREATED)
else:
error = {
'message':"Can Not upload successfully!",
'customers':"[]",
'error': customer_serializer.errors
}
return JsonResponse(error, status=status.HTTP_400_BAD_REQUEST)
except:
exceptionError = {
'message': "Can Not upload successfully!",
'customers': "[]",
'error': "Having an exception!"
}
return JsonResponse(exceptionError, status=status.HTTP_500_INTERNAL_SERVER_ERROR);
Django GET request
For getting all Customer entities from database with Django GET request, we do a list of 4 steps as following:
- Get all Customer’ entities via Customer model class
- Serialize a List of Customer Objects
- Return a JsonResponse object with Python dictionary body and http status code
JsonResponse(response, status=status.HTTP_200_OK);
- If having any error or exception, just return a JsonResponse object with a building body for errors and a http status error code:
JsonResponse(error, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
if request.method == 'GET':
try:
customers = Customer.objects.all()
customers_serializer = CustomerSerializer(customers, many=True)
response = {
'message': "Get all Customers'Infos Successfully",
'customers': customers_serializer.data,
'error': ""
}
return JsonResponse(response, status=status.HTTP_200_OK);
except:
error = {
'message': "Fail! -> can NOT get all the customers List. Please check again!",
'customers': "[]",
'error': "Error"
}
return JsonResponse(error, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
Django PUT request
In ./customers/views.py
file, We define a view function customer_detail to do a PUT/DELETE a Customer entity with a given id:
@api_view(['PUT', 'DELETE'])
def customer_detail(request, pk)
For PUT/DELETE a database entity with a given id, firstly we need to check the existing of an entity with the id. If having an DoesNotExist
exception throws, we stop processing the request and return a JsonResponse
object with a body is an exception’s error and a http status code NOT_FOUND
:
try:
customer = Customer.objects.get(pk=pk)
except Customer.DoesNotExist:
exceptionError = {
'message': "Not found a Customer with id = %s!" % pk,
'customers': "[]",
'error': "404 Code - Not Found!"
}
return JsonResponse(exceptionError, status=status.HTTP_404_NOT_FOUND)
For handing a PUT request, we do a list actions with 4 steps:
- Parsing the request’s body object
customer_data = JSONParser().parse(request)
- De-serialize the above parsing data:
customer_serializer = CustomerSerializer(customer, data=customer_data)
- Store the object to database by .save() API function:
customer_serializer.save() Return a JsonResponse object with user-defined response: response = { 'message': "Successfully Update a Customer with id = %s" % pk, 'customers': [customer_serializer.data], 'error': "" } return JsonResponse(response)
- If having any exception being throwed, we need to handle it and return an error with 404 status code:
return JsonResponse(response, status=status.HTTP_400_BAD_REQUEST)
try:
customer_data = JSONParser().parse(request)
customer_serializer = CustomerSerializer(customer, data=customer_data)
if customer_serializer.is_valid():
customer_serializer.save()
response = {
'message': "Successfully Update a Customer with id = %s" % pk,
'customers': [customer_serializer.data],
'error': ""
}
return JsonResponse(response)
response = {
'message': "Fail to Update a Customer with id = %s" % pk,
'customers': [customer_serializer.data],
'error': customer_serializer.errors
}
return JsonResponse(response, status=status.HTTP_400_BAD_REQUEST)
Django DELETE request
Here is the remain code in the view function def customer_detail(request, pk)
for DELETE request with a given id:
if request.method == 'GET':
customer_serializer = CustomerSerializer(customer)
response = {
'message': "Successfully get a Customer with id = %s" % pk,
'customers': [customer_serializer.data],
'error': ""
}
return JsonResponse(response, status=status.HTTP_200_OK);
...
elif request.method == 'DELETE':
print("Deleting a Customer with id=%s"%pk)
customer.delete()
customer_serializer = CustomerSerializer(customer)
response = {
'message': "Successfully Delete a Customer with id = %s" % pk,
'customers': [customer_serializer.data],
'error': ""
}
return JsonResponse(response)
Configure Django CRUD RestAPI URLs
We define a set of Rest URL for Customers Application in file ./customers/urls.py
:
from django.conf.urls import url
from customers import views
urlpatterns = [
url(r'^api/customers/$', views.customer_list),
url(r'^api/customers/(?P<pk>[0-9]+)$', views.customer_detail)
]
We need include the Customer Application’s URL file to project’s urls.py
file:
from django.contrib import admin
from django.urls import path
from django.conf.urls import url, include
urlpatterns = [
url(r'^', include('customers.urls')),
path('admin/', admin.site.urls),
]
Integrative Testing – Django + PostgreSQL CRUD RestAPIs
Testcase 1 – Django Post request to PostgreSQL

Testcase 2 – Django Get request: retrieve all data from PostgreSQL

Testcase 3 – Django Put request: update a data from PostgreSQL

Testcase 4 – Django Delete request: remove a record from PostgreSQL

Angular 9 CRUD Application Example – Frontend Development
Angular 9 CRUD Application Overview with Django RestAPIs

– For more details, we go back to the session: Angular CRUD Design
Create Angular 9 Application
We create Angular 9 CRUD project by commandline: ng new AngularHttpclient
.
– Create 3 components AddCustomer
, ListCustomers
, Message
by cmd:
ng g component AddCustomer
ng g component ListCustomers
ng g component Message
– Create 2 Angular services CustomerService
, MessageService
by cmd:
ng g service customer
ng g service message
– Create 2 models Customer
and Message
by cmd:
ng g class customer;
ng g class message;
Create Angular 9 Typescript Model
We define Customer
class with 5 attributes:
export class Customer {
id: number;
firstname: string;
lastname: string;
age: number;
address: string
}
Create Typescript Message
We define Message
class as below:
import { Customer } from './customer';
export class Message {
message: string;
error: string;
customers: Customer[];
}
Implement Angular 9 CRUD HttpClient Service
For interacting with Backend RestAPIs, we use Angular 9 built-in Httpclient service:
@Injectable({
providedIn: 'root'
})
export class CustomerService {
private baseUrl = 'http://localhost:8080/api/customers';
constructor(private http: HttpClient) { }
...
To handle Error, we implement a function private handleError(error: HttpErrorResponse)
:
private handleError(error: HttpErrorResponse) {
if (error.error instanceof ErrorEvent) {
// A client-side or network error occurred. Handle it accordingly.
console.error('An error occurred:', error.error.message);
} else {
// The backend returned an unsuccessful response code.
// The response body may contain clues as to what went wrong,
console.error(
`Backend returned code ${error.status}, ` +
`body was: ${error.error}`);
}
// return an observable with a user-facing error message
return throwError(
'Something bad happened; please try again later.');
};
Angular 9 HttpClient Post request
createCustomer(customer: Customer): Observable<Message> {
return this.http.post<Message>(`${this.baseUrl}` + `/create`, customer)
.pipe(
retry(3),
catchError(this.handleError)
);
}
– The above function posts a Customer to Django CRUD RestAPIs backend server at URL http://localhost:8080/api/customers/create
– retry(3)
is used to retry a failed request up to 3 times
Angular 9 HttpClient Get request
– Angular 9 Client retrieve all data from PostgreSQL via Django rest CRUD backend by a GET request at URL http://localhost:8080/api/customers/retrieveinfos
.
retrieveAllCustomers(): Observable {
return this.http.get(`${this.baseUrl}` + `/retrieveinfos`)
.pipe(
retry(3),
catchError(this.handleError)
);
}
Angular 9 HttpClient Put request
– Angular 9 client updates a data using Angular 9 built-in Httpclient by a PUT request at URL:
http://localhost:8080/api/customers/updatebyid/{id}
updateCustomer(customer: Customer): Observable<Message> {
return this.http.put<Message> (`${this.baseUrl}` + `/updatebyid/` + customer.id, customer)
.pipe(
retry(3),
catchError(this.handleError)
);
}
Angular 9 HttpClient Delete request
– Angular 9 client deletes a data from PostgreSQL by a given id
using built-in Angular Httpclient by a Delete request at URL:
http://localhost:8080/api/customers/deletebyid/{id}
:
deleteCustomer(id: number): Observable<Message> {
return this.http.delete<Message>(`${this.baseUrl}` + `/deletebyid/` + id)
.pipe(
retry(3),
catchError(this.handleError)
);
}
Implement Angular 9 post/get/put/delete components
Implement Angular 9 Message Service
For tracking the proccessing of each step of Angular 9 CRUD Application, we implement a Message service to store tracing-logs message then display them on Html.
The message.service.ts
has an string array messages
to store tracing-log messages and 2 functions: add(message: string)
and clear()
– Coding:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class MessageService {
messages: string[] = [];
add(message: string) {
this.messages.push(message);
}
clear(){
this.messages = [];
}
}
Implement Angular 9 Post Component: adding data
AddCustomerComponent
is used to post a new data Customer to PostgreSQL via Django CRUD Application server.
– We have 2 parts:
add-customer.component.ts
fileadd-cusomer.component.html
file
1. add-customer.component.ts
file
import { Component, OnInit } from '@angular/core';
import { Customer } from '../customer';
import { CustomerService } from '../customer.service';
import { Message } from '../message';
import { MessageService } from '../message.service';
@Component({
selector: 'app-add-customer',
templateUrl: './add-customer.component.html'
})
export class AddCustomerComponent implements OnInit {
customer: Customer;
/**
* Constructing Http Customer Service
* @param customerService
*/
constructor(private customerService: CustomerService,
private messageService: MessageService) { }
ngOnInit(): void {
this.customer = new Customer();
}
/**
* Store a Customer to backend server
*/
save() {
this.customerService.createCustomer(this.customer)
.subscribe((message: Message) => {
console.log(message);
let customer = message.customers[0];
let msg = "Success -> Post a Customer: "
+ "<ul>"
+ "<li>id: " + customer.id + "</li>"
+ "<li>firstname: " + customer.firstname + "</li>"
+ "<li>lastname: " + customer.lastname + "</li>"
+ "<li>age: " + customer.age + "</li>"
+ "<li>address: " + customer.address + "</li>"
+ "</ul>";
this.messageService.add(msg);
}, error => {
console.log(error);
let msg = "Error! -> Action Posting a Customer:"
+ "<ul>"
+ "<li>id = " + this.customer.id + "</li>"
+ "<li>firstname = " + this.customer.firstname + "</li>"
+ "<li>lastname = " + this.customer.lastname + "</li>"
+ "<li>age = " + this.customer.age + "</li>"
+ "<li>address = " + this.customer.address + "</li>"
+ "</ul>";
this.messageService.add(msg);
});
}
reset(){
this.customer = new Customer();
}
/**
* Function handles form submitting
*/
onSubmit() {
this.save();
this.reset();
}
}
2. Implement add-customer.component.html
view:
<h2>Create Customer</h2>
<div>
<form (ngSubmit)="onSubmit()">
<!-- First name -->
<div class="form-group">
<label for="firstname">First Name:</label>
<input type="text" class="form-control" placeholder="Enter Firstname"
id="firstname" required [(ngModel)]="customer.firstname" name="firstname">
</div>
<!-- Last name -->
<div class="form-group">
<label for="lastname">Last Name:</label>
<input type="text" class="form-control" placeholder="Enter Lastname"
id="lastname" required [(ngModel)]="customer.lastname" name="lastname">
</div>
<!-- Address -->
<div class="form-group">
<label for="address">Address:</label>
<input type="text" class="form-control" placeholder="Enter Address"
id="address" required [(ngModel)]="customer.address" name="address">
</div>
<!-- Age -->
<div class="form-group">
<label for="age">Age</label>
<input type="number" class="form-control" placeholder="Enter Age"
id="age" required [(ngModel)]="customer.age" name="age">
</div>
<button type="submit" class="btn btn-success">Submit</button>
</form>
</div>
<app-message></app-message>
Implement Angular 9 List Component: retrieve all data
ListCustomersComponent
has 4 main functions:
- Show all Customers
- Show details a Customers
- Delete a Customer
- Update a Customer
1. Implement list-customers.component.ts
:
import { Component, OnInit } from '@angular/core';
import { Customer } from '../customer';
import { MessageService } from '../message.service';
import { CustomerService } from '../customer.service';
import { Message } from '../message';
@Component({
selector: 'app-list-customers',
templateUrl: './list-customers.component.html'
})
export class ListCustomersComponent implements OnInit {
customers: Array<Customer> = [];
showCustomer: Customer;
isSelected: boolean = false;
deletedCustomer: Customer;
returnedMessage: string;
constructor(private customerService: CustomerService,
private messageService: MessageService) { }
setCustomerDetails(customer: Customer){
this.isSelected=!this.isSelected;
if(this.isSelected){
this.showCustomer = customer;
}else{
this.showCustomer = undefined;
}
}
/**
* Set deletedCustomer and reset returnedMessage = undefined
* @param deleteCustomer
*/
prepareDeleteCustomer(deleteCustomer: Customer){
//assign delete-Customer
this.deletedCustomer = deleteCustomer;
// reset returned-Message
this.returnedMessage = undefined;
}
/**
* Delete a Customer by ID
*/
deleteCustomer(){
console.log("--- Access delelteCustomer() function");
this.customerService.deleteCustomer(this.deletedCustomer.id)
.subscribe((message: Message) => {
console.log(message);
// remove a deletedCustomer from customers list on view
this.customers = this.customers.filter(customer => {
return customer.id != this.deletedCustomer.id;
})
// set a showing message in delete modal
this.returnedMessage = message.message;
// just reset showCustomer for not showing on view
this.showCustomer = undefined;
// add the delete message to message app for showing
this.messageService.add(message.message);
},
(error) => {
console.log(error);
let errMsg: string = "Error! Details: " + error;
this.messageService.add(errMsg);
});
}
/**
* Update Customer function
*/
updateCustomer() {
this.customerService.updateCustomer(this.showCustomer)
.subscribe((message: Message) => {
console.log(message);
// update customers list
this.customers.map(x => {
if(x.id == this.showCustomer.id){
x = this.showCustomer;
}
});
let msg: string = "Update Successfully! -> New Customer's properties: <br>"
+ "<ul>"
+ "<li>" + "id: " + this.showCustomer.id + "</li>"
+ "<li>" + "firstname: " + this.showCustomer.firstname + "</li>"
+ "<li>" + "lastname: " + this.showCustomer.lastname + "</li>"
+ "<li>" + "age: " + this.showCustomer.age + "</li>"
+ "<li>" + "address: " + this.showCustomer.address + "</li>"
+ "</ul>";
this.messageService.add(msg);
}
, (error) => {
console.log(error);
let errMsg = "Update Fail ! Error = " + error;
this.messageService.add(errMsg);
});
}
/**
* Retrieve all Customer from Backend
*/
retrieveAllCustomers() {
this.customerService.retrieveAllCustomers()
.subscribe((message: Message) => {
console.log(message);
this.customers = message.customers;
}
, (error) => {
console.log(error);
});
}
ngOnInit(): void {
this.retrieveAllCustomers();
}
}
2. Implement list-customers.component.html
:
<div *ngIf="customers.length">
<h3>Customers</h3>
<br>
<table class="table table-hover table-sm">
<thead class="thead-dark">
<tr>
<th>Id</th>
<th>Firstname</th>
<th>Address</th>
<th></th>
</tr>
</thead>
<tbody>
<tr *ngFor="let customer of customers">
<td>
<button type="button" class="btn btn-primary" (click)="setCustomerDetails(customer)">
{{customer.id}}
</button>
</td>
<td>{{customer.firstname}}</td>
<td>{{customer.address}}</td>
<td>
<button type="button" class="btn btn-danger"
data-toggle="modal" data-target="#delete-modal"
(click)=prepareDeleteCustomer(customer) >×</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- The Modal -->
<div class="modal fade" id="delete-modal">
<div class="modal-dialog modal-dialog-centered">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<h4 class="modal-title">Delete!</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<!-- Modal body -->
<div class="modal-body">
<div *ngIf="deletedCustomer">
<p [hidden] = "returnedMessage">
Do you want delete a customer with id = {{deletedCustomer.id}}
</p>
<p [hidden] = "!returnedMessage">
{{returnedMessage}}
</p>
</div>
</div>
<!-- Modal footer -->
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button [hidden] = "returnedMessage" type="button" class="btn btn-danger" (click)="deleteCustomer()">Delete</button>
</div>
</div>
</div>
</div>
<div *ngIf="showCustomer">
<h3>Update Customer</h3>
<form (ngSubmit)="updateCustomer()">
<!-- ID -->
<div class="form-group">
<label for="id">Id:</label>
<input type="numer" class="form-control"
id="id" required [(ngModel)]="showCustomer.id" name="id" disabled>
</div>
<!-- First name -->
<div class="form-group">
<label for="firstname">First Name:</label>
<input type="text" class="form-control" placeholder="Enter Firstname"
id="firstname" required [(ngModel)]="showCustomer.firstname" name="firstname">
</div>
<!-- Last name -->
<div class="form-group">
<label for="lastname">Last Name:</label>
<input type="text" class="form-control" placeholder="Enter Lastname"
id="lastname" required [(ngModel)]="showCustomer.lastname" name="lastname">
</div>
<!-- Address -->
<div class="form-group">
<label for="address">Address:</label>
<input type="text" class="form-control" placeholder="Enter Address"
id="address" required [(ngModel)]="showCustomer.address" name="address">
</div>
<!-- Age -->
<div class="form-group">
<label for="age">Age</label>
<input type="number" class="form-control" placeholder="Enter Age"
id="age" required [(ngModel)]="showCustomer.age" name="age">
</div>
<button type="submit" class="btn btn-success">Update</button>
</form>
</div>
<app-message></app-message>
<script>
let pathname = window.location.pathname;
if(pathname == ""){
$(".nav .nav-item a:first").addClass("active");
$(".nav .nav-item a:last").removeClass("active");
} else if (pathname == "/customers") {
$(".nav .nav-item a:last").addClass("active");
$(".nav .nav-item a:first").removeClass("active");
}
alert("ok");
</script>
Implement Angular 9 Message Component
MessageComponent
is used to show all tracing-log messages in html view.
1. Implement message.component.ts
:
import { Component, OnInit } from '@angular/core';
import { MessageService } from '../message.service';
@Component({
selector: 'app-message',
templateUrl: './message.component.html'
})
export class MessageComponent {
constructor(public messageService: MessageService) {}
}
2. Implement message.component.html
:
<div *ngIf="messageService.messages.length">
<h3>Messages</h3>
<button type="button" class="btn btn-secondary" (click)="messageService.clear()">clear</button>
<br>
<ol>
<li *ngFor='let message of messageService.messages'>
<div [innerHTML]="message">
</div>
</li>
</ol>
</div>
Configure Angular 9 Routing Module
To handle the navigation from one view to the next, you use the Angular 9 router. The router enables navigation by interpreting a browser URL as an instruction to change the view.
The following command uses the Angular CLI to generate a basic Angular app with an app routing module, called AppRoutingModule
, which is an NgModule where you can configure your routes.
ng new routing-app --routing
How to Define a route? -> There are three fundamental building blocks to creating a route.
1. Import the AppRoutingModule into AppModule and add it to the imports array.
The Angular CLI performs this step for you. However, if you are creating an app manually or working with an existing, non-CLI app, verify that the imports and configuration are correct.
import { AppRoutingModule } from './app-routing.module';
...
@NgModule({
declarations: [
...
],
imports: [
...
AppRoutingModule,
...
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }
2. Define your routes in your Routes array for “Angular 9 Django PostgreSQL CRUD Example”:
import { NgModule } from '@angular/core';
import { Routes, RouterModule } from '@angular/router';
import { AddCustomerComponent } from './add-customer/add-customer.component';
import { ListCustomersComponent } from './list-customers/list-customers.component';
const routes: Routes = [
{
path: '',
component: AddCustomerComponent
},
{
path: 'customers',
component: ListCustomersComponent
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
3. Add your routes to your application.
In the index.html
file, we add below html code for navigating URL:
<nav class="navbar navbar-expand-sm bg-primary navbar-dark">
<ul class="navbar-nav">
<li class="nav-item" id="li_add_customer">
<a class="nav-link" href="">Add Customer</a>
</li>
<li class="nav-item" id="li_list_customers">
<a class="nav-link" href="/customers">List Customers</a>
</li>
</ul>
</nav>
Next, update your component template to include app.component.ts
file, add the tag:
<router-outlet></router-outlet>
Modify Index.html View Page
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>AngularHttpclient</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
<!-- jQuery library -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!-- Popper JS -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
<!-- Latest compiled JavaScript -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container" >
<div class="col-sm-5" style="background-color: #ffffcc; margin:10px;padding:10px; border-radius: 5px">
<nav class="navbar navbar-expand-sm bg-primary navbar-dark">
<ul class="navbar-nav">
<li class="nav-item" id="li_add_customer">
<a class="nav-link" href="">Add Customer</a>
</li>
<li class="nav-item" id="li_list_customers">
<a class="nav-link" href="/customers">List Customers</a>
</li>
</ul>
</nav>
<app-root></app-root>
</div>
</div>
<script>
$(document).ready(function() {
(function(){
let pathname = window.location.pathname;
if(pathname == "/"){
$("#li_add_customer").addClass("active");
$("#li_list_customers").removeClass("active");
} else if (pathname == "/customers") {
$("#li_list_customers").addClass("active");
$("#li_add_customer").removeClass("active");
}
})();
});
</script>
</body>
</html>
Integrative Testing: Angular 9 Application with Django CRUD RestAPIs + PostgreSQL
Okay, now we do a set of testcases for the tutorial: “Angular 9 Django PosgreSQL CRUD Example using Django Rest framework”.
Testcase 1: Angular 9 Post data to PostgreSQL


Testcase 2: Angular 9 Get All data from PostgreSQL


Testcase 3: Angular 9 Put data to PostgreSQL


Testcase 4: Angular 9 Delete data from PostgreSQL

Check PostgreSQL database:

Sourcecode
Below is clearly running sourcecode for the tutorial “Django Python Angular 9 PostgreSQL CRUD RestAPI Example”:
1. Django PostgreSQL CRUD RestAPIs Application
Django PostgreSQL CRUD Example
2. Angular 9 CRUD Application:
– Github sourcecode for the tutorial: “Angular 9 Django PostgreSQL CRUD Example”
Django PostgreSQL CRUD Example