In this tutorial, we will learn how to build a full stack Django + Angular + MySQL example with a CRUD App. The back-end server uses Python 3/Django with Rest Framework for REST APIs. Front-end side is made with Angular 15/14/13/12/11/10/8, HTTPClient & Router.
Contents
- Django + Angular + MySQL example Overview
- Django + Angular + MySQL Architecture
- Django Rest Apis Back-end
- Overview
- Technology
- Project structure
- Install Django REST framework
- Setup new Django project
- Connect Django project to MySQL
- Setup new Django app for Rest CRUD Api
- Configure CORS
- Define the Django Model
- Migrate Data Model to the database
- Create Serializer class for Data Model
- Define Routes to Views functions
- Write API Views
- Run the Django Rest Api Server
- Angular Front-end
- Further Reading
- Conclusion
Django + Angular + MySQL example Overview
We will build a full-stack Django + Angular Tutorial Application working with MySQL database in that:
- Each Tutorial has id, title, description, published status.
- We can create, retrieve, update, delete Tutorials.
- We can also find Tutorials by title.
The images below shows screenshots of our System.
– Create an item:
– Retrieve all items:
– Click on Edit button to view an item details:
On this Page, you can:
- change status to Published using Publish button
- remove the Tutorial from Database using Delete button
- update the Tutorial details on Database with Update button
– Search items by title:
Django + Angular + MySQL Architecture
This is the application architecture we’re gonna build:
– Django exports REST Apis using Django Rest Framework & interacts with MySQL Database using Django Model.
– Angular 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.
Django Rest Apis Back-end
Overview
The following diagram shows the architecture of our Django CRUD Rest Apis App with MySQL database:
- HTTP requests will be matched by Url Patterns and passed to the Views
- Views processes the HTTP requests and returns HTTP responses (with the help of Serializer)
- Serializer serializes/deserializes data model objects
- Models contains essential fields and behaviors for CRUD Operations with MySQL Database
These are APIs that Django App will export:
Methods | Urls | Actions |
---|---|---|
POST | /api/tutorials | create new Tutorial |
GET | /api/tutorials | retrieve all Tutorials |
GET | /api/tutorials/:id | retrieve a Tutorial by :id |
PUT | /api/tutorials/:id | update a Tutorial by :id |
DELETE | /api/tutorials/:id | delete a Tutorial by :id |
DELETE | /api/tutorials | delete 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
- django-cors-headers 3.2.1
Project structure
This is our Django project structure:
Let me explain it briefly.
- tutorials/apps.py: declares
TutorialsConfig
class (subclass ofdjango.apps.AppConfig
) that represents Rest CRUD Apis app and its configuration. - bzkRestApisMySQL/settings.py: contains settings for our Django project: MySQL Database engine,
INSTALLED_APPS
list with Django REST framework, Tutorials Application, CORS andMIDDLEWARE
. - 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 MySQL database table.
- tutorials/serializers.py: manages serialization and deserialization with
TutorialSerializer
class (subclass ofrest_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.
- bzkRestApisMySQL/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 bzkRestApisMySQL
When the process is done, you can see folder tree like this:
Now we open settings.py and add Django REST framework to the INSTALLED_APPS
array here.
INSTALLED_APPS = [
...
# Django REST framework
'rest_framework',
]
Connect Django project to MySQL
We need a MySQL Client to work with MySQL database.
In this tutorial, we’re gonna use pymysql.
Run the command to install it: pip install pymysql
.
Then open __init__.py and write following code to import pymysql
to our Django project:
import pymysql
pymysql.install_as_MySQLdb()
We also need to setup MySQL Database engine.
So open settings.py and change declaration of DATABASES
:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'testdb',
'USER': 'root',
'PASSWORD': '123456',
'HOST': '127.0.0.1',
'PORT': '3306',
}
}
Setup new Django app for Rest CRUD Api
Run following commands to create new Django app tutorials:
cd bzkRestApisMySQL
python manage.py startapp tutorials
Refresh the project directory tree, you can see it now looks like:
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 toFalse
. - 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: title, description, published.
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 Customer 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 for Tutorial
model was generated automatically with the name: tutorials_tutorial:
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 Serializerfields
: 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 url
s 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 bzkRestApisMySQL/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
You can continue with step by step to implement this Django Server in the post:
Django CRUD with MySQL example | Django Rest Framework
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 'bzkRestApisMySQL.settings'
Starting development server at http://127.0.0.1:8080/
Quit the server with CTRL-BREAK.
Angular Front-end
Overview
– 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.
– Tutorial
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.
Project Structure
– tutorial.model.ts
exports the main class model: Tutorial
.
– There are 3 components: tutorials-list
, tutorial-details
, add-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 Angular11Crud
? 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
Set up App Module
Open app.module.ts and import FormsModule
, HttpClientModule
:
...
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 { Routes, RouterModule } 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 { }
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
You can continue with step by step to implement this Angular App (with Github) in one of following posts:
– Angular 8 CRUD example with Web API
– Angular 10 CRUD example with Web API
– Angular 11 CRUD example with Web API
– Angular 12 CRUD example with Web API
– Angular 13 CRUD example with Web API
– Angular 14 CRUD example with Web API
– Angular 15 CRUD example with Web API
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.
Further Reading
- Django Rest Framework quich start
- Django Model
- https://github.com/PyMySQL/PyMySQL
- Angular HttpClient
- Angular Template Syntax
Other back-end servers that work well with the Angular Client:
Conclusion
Now we have an overview of Django + Angular + MySQL example when building a CRUD App that interacts with database. We also take a look at client-server architecture for REST API using Django Rest Framework (Python 3), as well as Angular project structure for building a front-end app to make HTTP requests and consume responses.
Next tutorials show you more details about how to implement the system (including Github source code):
– Back-end
– Front-end:
- Using Angular 8
- Using Angular 10
- Using Angular 11
- Using Angular 12
- Using Angular 13
- Using Angular 14
- Using Angular 15