Django + Angular 6 example | Django Rest Framework + MySQL CRUD example – Part 2: Django Server

django-angular-6-django-rest-api-mysql-angular-django-project-structure-feature-image

This tutorial is part 2 of Django-Angular-MySQL series. Today, we will create Django server to do CRUD with MySQL (including finder method).

>> Part 1: Overview
>> Part 3: Angular Client

Related Post:
Django RestApis example – GET/POST/PUT/DELETE requests MySQL database with Django REST Framework

Video

Django RestApi server Overview

Goal

Our Django Server can work with MySQL Database and provides APIs:

  • GET /customers/: get all customers
  • GET /customers/[id]: get a customer by id
  • GET /customers/age/[age]: find all customers by age
  • POST /customers/: save a customer
  • PUT /customers/[id]: update a customer by id
  • DELETE /customers/[id]: delete a customer by id
  • DELETE /customers/: delete all customers
Architecture

django-angular-6-django-rest-api-mysql-angular-server-architecture

Project structure

There are several folders and files in our Django project:

django-angular-6-django-rest-api-mysql-angular-django-project-structure

customers/apps.py: declares CustomersConfig class (subclass of the django.apps.AppConfig) that represents our Django app and its configuration.
gkzRestApi/settings.py: configures settings for the Django project, including INSTALLED_APPS list with Django REST framework and Customers Application.
customers/models.py: defines Customer data model class (subclass of the django.db.models.Model).
migrations/0001_initial.py: is generated by makemigrations command, includes the code to create the Customer model, will be run by migrate to generate MySQL database table for Customer model.
customers/serializers.py: declares CustomerSerializer class (subclass of rest_framework.serializers.ModelSerializer) for Customer instances to manage serialization to JSON and deserialization from JSON.
customers/views.py: contains methods to process HTTP requests and produce HTTP responses (using CustomerSerializer).
customers/urls.py: defines urlpatterns to be matched with request functions in the views.py.
gkzRestApi/urls.py: defines root URL configurations that includes the URL patterns declared in customers/urls.py.

Setup Django RestApi project

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 RestApi project

Create Django project named gkzRestApi with command:
django-admin startproject gkzRestApi

django-angular-6-django-rest-api-mysql-angular-django-create-project

Install & Import Python MySQL Client

We have to install Python MySQL Client to work with MySQL database.
In this tutorial, we use pymysql: pip install pymysql.

Once the installation is successful, import this module in gkzRestApi/__init__.py:

import pymysql

pymysql.install_as_MySQLdb()
Setup MySQL Database engine

Open gkzRestApi/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',
    }
}
Create Customers App

Run following commands to create new Django App named customers:
cd gkzRestApi
python manage.py startapp customers

django-angular-6-django-rest-api-mysql-angular-django-create-project-app

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'
Add Django Rest framework & RestApi App to Django project

Open gkzRestApi/settings.py, find INSTALLED_APPS, then add:

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',
]
Add CORS Configurations

Inside gkzRestApi/settings.py, add:

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

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',  
]

CORS_ORIGIN_ALLOW_ALL = False
CORS_ORIGIN_WHITELIST = (
    'localhost:4200',
)

Implement Django RestApi App

Data Model
Create Data Model

customers/models.py

from django.db import models


class Customer(models.Model):
    name = models.CharField(max_length=70, blank=False, default='')
    age = models.IntegerField(blank=False, default=1)
    active = models.BooleanField(default=False)
Run initial migration for data model

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 2.1.7 on 2019-02-17 08:10

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')),
                ('name', models.CharField(default='', max_length=70)),
                ('age', models.IntegerField(default=1)),
                ('active', models.BooleanField(default=False)),
            ],
        ),
    ]

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 MySQL Database, now we can see that a table for Customer model was generated and it’s named customers_customer:

django-angular-6-django-rest-api-mysql-angular-django-mysql-table

Create Serializer class

We need a Serializer class for Customer instances to manage serialization to JSON and deserialization from JSON.

– This CustomerSerializer 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',
                  'name',
                  'age',
                  'active')

Meta inner class declares 2 attributes:
model: specifies the model related to the serializer
fields: specifies a tuple of field names that we want to include in the serialization

Create API Views

Open customers/views.py file and declare two functions:
customer_list(): get list of customers, save a new customer, delete all customers
customer_detail(): get/update/delete customer by ‘id’
customer_list_age(): find all customers by ‘age’

from django.shortcuts import render 
from django.http import HttpResponse
from django.http.response import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.parsers import JSONParser 
from rest_framework import status

from customers.models import Customer
from customers.serializers import CustomerSerializer


@csrf_exempt
def customer_list(request):
    if request.method == 'GET':
        customers = Customer.objects.all()
        customers_serializer = CustomerSerializer(customers, many=True)
        return JsonResponse(customers_serializer.data, safe=False)
        # In order to serialize objects, we must set 'safe=False'

    elif request.method == 'POST':
        customer_data = JSONParser().parse(request)
        customer_serializer = CustomerSerializer(data=customer_data)
        if customer_serializer.is_valid():
            customer_serializer.save()
            return JsonResponse(customer_serializer.data, status=status.HTTP_201_CREATED) 
        return JsonResponse(customer_serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
    elif request.method == 'DELETE':
        Customer.objects.all().delete()
        return HttpResponse(status=status.HTTP_204_NO_CONTENT)


@csrf_exempt 
def customer_detail(request, pk):
    try: 
        customer = Customer.objects.get(pk=pk) 
    except Customer.DoesNotExist: 
        return HttpResponse(status=status.HTTP_404_NOT_FOUND) 
 
    if request.method == 'GET': 
        customer_serializer = CustomerSerializer(customer) 
        return JsonResponse(customer_serializer.data) 
 
    elif request.method == 'PUT': 
        customer_data = JSONParser().parse(request) 
        customer_serializer = CustomerSerializer(customer, data=customer_data) 
        if customer_serializer.is_valid(): 
            customer_serializer.save() 
            return JsonResponse(customer_serializer.data) 
        return JsonResponse(customer_serializer.errors, status=status.HTTP_400_BAD_REQUEST) 
 
    elif request.method == 'DELETE': 
        customer.delete() 
        return HttpResponse(status=status.HTTP_204_NO_CONTENT)

    
@csrf_exempt
def customer_list_age(request, age):
    customers = Customer.objects.filter(age=age)
        
    if request.method == 'GET': 
        customers_serializer = CustomerSerializer(customers, many=True)
        return JsonResponse(customers_serializer.data, safe=False)
        # In order to serialize objects, we must set 'safe=False'
Route Urls to Views functions

Create urls.py in customers folder, now we will define urlpatterns to be matched with request functions in the views.py.

from django.conf.urls import url 
from customers import views 
 
urlpatterns = [ 
    url(r'^customers/$', views.customer_list),
    url(r'^customers/(?P<pk>[0-9]+)$', views.customer_detail),
    url(r'^customers/age/(?P<age>[0-9]+)/$', views.customer_list_age),
]

Now we must include above URL patterns in root URL configurations.
Open gkzRestApi/urls.py, replace the code:

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

Source Code

Django-RestApi-server-MySQL

4 thoughts on “Django + Angular 6 example | Django Rest Framework + MySQL CRUD example – Part 2: Django Server”

  1. Great beat ! I wish to apprentice while you amend your web site, how can i subscribe for a blog website?
    The account helped me a acceptable deal. I had been a little bit acquainted of
    this your broadcast provided bright clear idea

  2. I discovered your blog site on google and verify just a few of your early posts. Continue to keep up the very good operate. I simply additional up your RSS feed to my MSN Information Reader. Searching for ahead to studying extra from you afterward!?

Leave a Reply

Your email address will not be published. Required fields are marked *