From Zero to Full Stack | A Simple Yet Fully Functional React, Django, and MySQL App

From Zero to Full Stack | A Simple Yet Fully Functional React, Django, and MySQL App

Part 1: Backend

In this series of 2 articles, we will build a basic application using the React + Django + MySQL stack. The system will include user authentication, product CRUD operations, and communication between the frontend and backend.

Let’s start with the backend and database.

Prerequisites

Before starting, you need to have installed:

  • Python 3

  • Node.js and npm/yarn

  • MySQL

  • Postman or Insomnia to test the API

To check all instalations:

node -v
npm -v
python --version
mysql -u root -p

  1. Create the Virtual Environment and Install Dependencies

python3 -m venv django_venv  # Use py or python3, depending on your python version

source django_venv/bin/activate  # On Linux or Mac

django_venv\Scripts\activate # On Windows

pip install django djangorestframework mysqlclient django-cors-headers

django – This is the core Django framework, a high-level Python web framework that promotes rapid development and clean, pragmatic design.

djangorestframework – Also known as DRF, this is a powerful and flexible toolkit for building Web APIs in Django. It provides serialization, authentication, and permission handling, making it easier to create RESTful APIs.

mysqlclient – This is a MySQL database adapter for Python, used to connect Django with a MySQL database. It provides the necessary drivers to interact with MySQL databases efficiently.

django-cors-headers – This package allows handling Cross-Origin Resource Sharing (CORS) in Django applications. It helps configure and manage security policies that enable or restrict requests from different origins (domains), which is crucial when building APIs that will be consumed by front-end applications hosted elsewhere.

  1. Create the Django Project

django-admin startproject backend
cd backend
python manage.py startapp api

  1. Configure Backend Settings in settings.py

  • Basic Django Settings :

import os
from pathlib import Path

# Get the base directory of the project
BASE_DIR = Path(__file__).resolve().parent.parent

# Secret key used for cryptographic signing (change this in production)
SECRET_KEY = 'your_secret_key_here'

# Debug mode: should be False in production to prevent security risks
DEBUG = True  

# Allowed hosts: specify the domains that can serve the application
ALLOWED_HOSTS = ['*']  # Define allowed hosts in production
  • Configure the Installed Apps:

# List of installed applications in the Django project
INSTALLED_APPS = [
    # Default Django applications
    'django.contrib.admin',         # Admin interface
    'django.contrib.auth',          # Authentication system
    'django.contrib.contenttypes',  # Content type framework
    'django.contrib.sessions',      # Session management
    'django.contrib.messages',      # Messaging framework
    'django.contrib.staticfiles',   # Static file handling
    # Added third-party apps
    'rest_framework',               # Django REST framework for building APIs
    'rest_framework.authtoken',     # Token-based authentication for APIs
    'corsheaders',                  # Handles Cross-Origin Resource Sharing (CORS)
    # Custom app
    'api',  # Application containing project-specific logic
]
  • Configure the Middlewares:

# List of middleware components used in the Django project
MIDDLEWARE = [
    # Added third-party middleware
    'corsheaders.middleware.CorsMiddleware',  # Handles Cross-Origin Resource Sharing (CORS)
    # Standard Django middleware
    'django.middleware.security.SecurityMiddleware',  # Provides security enhancements
    'django.contrib.sessions.middleware.SessionMiddleware',  # Manages user sessions
    'django.middleware.common.CommonMiddleware',  # Adds common functionalities like URL rewriting
    'django.middleware.csrf.CsrfViewMiddleware',  # Protects against CSRF attacks
    'django.contrib.auth.middleware.AuthenticationMiddleware',  # Handles user authentication
    'django.contrib.messages.middleware.MessageMiddleware',  # Enables messaging framework
    'django.middleware.clickjacking.XFrameOptionsMiddleware',  # Protects against clickjacking attacks
]
  • Configure the MySQL Database:

# Database configuration settings
DATABASES = {
    'default': {
        # Database engine (MySQL in this case)
        'ENGINE': 'django.db.backends.mysql',
        # Name of the database
        'NAME': '[mydatabase]',
        # Database user
        'USER': 'root',
        # Database user password (change this in production)
        'PASSWORD': '[your_password]',
        # Host where the database is running (localhost for local development)
        'HOST': 'localhost',
        # Port number used by the database server (default for MySQL is 3306)
        'PORT': '3306',
    }
}
  • Configure the User Authentication:

# Custom user model used for authentication
AUTH_USER_MODEL = 'api.User'
# List of authentication backends
AUTHENTICATION_BACKENDS = [
    # Default authentication backend for Django
    'django.contrib.auth.backends.ModelBackend',  
]
# Django REST framework configuration
REST_FRAMEWORK = {
    # Default authentication classes
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # Token-based authentication for API requests
        'rest_framework.authentication.TokenAuthentication',  
    ],
    # Default permission classes
    'DEFAULT_PERMISSION_CLASSES': [
        # Requires users to be authenticated to access the API
        'rest_framework.permissions.IsAuthenticated',  
    ],
}
  • Configure Media and Static Files:

# URL path for serving static files (CSS, JavaScript, images, etc.)
STATIC_URL = '/static/'
# URL path for serving media files (uploaded by users)
MEDIA_URL = '/media/'
# Directory where media files will be stored
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# List of directories where static files are located
STATICFILES_DIRS = [
    os.path.join(BASE_DIR, 'static'),  # Includes a 'static' folder inside the project
]
💡
Create a directory called static in the outermost backend directory.
  • Configure CORS to Allow Requests from React:

# Allows requests from any domain (not recommended for production)
CORS_ALLOW_ALL_ORIGINS = True  # Allows requests from any domain

# List of specific origins allowed to make requests to the backend
CORS_ALLOWED_ORIGINS = [
    "http://localhost:3000",  # URL of the React frontend
]
  • Basic Password System Configuration:

# List of password validators to enforce security rules
AUTH_PASSWORD_VALIDATORS = [
    # Ensures that the password is not too similar to user attributes
    {'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator'},
    # Requires a minimum length for passwords
    {'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator'},
    # Prevents users from using common passwords
    {'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator'},
    # Disallows passwords that consist entirely of numeric characters
    {'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator'},
]
  • Internationalization and Time Zone Configurations:

# Default language code for the project
LANGUAGE_CODE = 'en-us'  # Sets English (United States) as the default language
# Time zone setting for the project
TIME_ZONE = 'UTC'  # Uses Coordinated Universal Time (UTC)
# Enables Django's internationalization system
USE_I18N = True  # Allows translation of text in the application
# Enables Django's localization system for formatting dates, numbers, etc.
USE_L10N = True  # Uses locale-specific formatting for data representation
# Enables time zone support for storing and handling datetime objects
USE_TZ = True  # Stores datetime values in UTC and converts them based on user settings

  1. Create the User and Product Models in models.py:

# Importing Django's built-in AbstractUser model for user authentication
from django.contrib.auth.models import AbstractUser, Group, Permission
from django.db import models

# Custom user model extending Django's AbstractUser
class User(AbstractUser):
    # Many-to-many relationship with Group, using a custom related name to avoid conflicts
    groups = models.ManyToManyField(
        Group,
        related_name="api_user_groups",  # Prevents conflict with 'auth.User.groups'
        blank=True  # Allows this field to be empty
    )
    # Many-to-many relationship with Permission, using a custom related name to avoid conflicts
    user_permissions = models.ManyToManyField(
        Permission,
        related_name="api_user_permissions",  # Prevents conflict with 'auth.User.user_permissions'
        blank=True  # Allows this field to be empty
    )

# Product model representing items available in the system
class Product(models.Model):
    # Product name with a maximum length of 255 characters
    name = models.CharField(max_length=255)
    # Product description as a text field
    description = models.TextField()
    # Product price, using a decimal field with up to 10 digits and 2 decimal places
    price = models.DecimalField(max_digits=10, decimal_places=2)
    # Foreign key linking the product to a user, with cascade deletion
    user = models.ForeignKey(User, on_delete=models.CASCADE)  
    # If the user is deleted, the product is also deleted

  1. Create serializers.py file at api folder:

# Importing the serializer module from Django REST framework
from rest_framework import serializers
# Importing the Product model
from .models import Product
# Serializer for the Product model
class ProductSerializer(serializers.ModelSerializer):
    class Meta:
        # Specifies the model to be serialized
        model = Product
        # Includes all fields from the Product model in the serialization
        fields = '__all__'

  1. Create API with Django Rest Framework in Views.py:

# Importing necessary modules from Django REST framework
from rest_framework import viewsets, permissions
from rest_framework.authentication import TokenAuthentication
# Importing the Product model and its serializer
from .models import Product
from .serializers import ProductSerializer

# ViewSet for managing Product data
class ProductViewSet(viewsets.ModelViewSet):
    # Retrieves all Product records from the database
    queryset = Product.objects.all()
    # Specifies the serializer class to handle Product data serialization
    serializer_class = ProductSerializer
    # Defines the authentication method (Token-based authentication)
    authentication_classes = [TokenAuthentication]
    # Requires users to be authenticated to access this view
    permission_classes = [permissions.IsAuthenticated]

  1. Create an urls.py File in api and Route the API :

from django.urls import path, include
from rest_framework.routers import DefaultRouter
from .views import ProductViewSet
from rest_framework.authtoken.views import obtain_auth_token

router = DefaultRouter()
router.register(r'products', ProductViewSet)

urlpatterns = [
    path('api/', include(router.urls)),
    path('api/token/', obtain_auth_token, name='api_token_auth'),
]

# Autentication Token EndPoint
# POST     /api/token/         Retrieve an access token

# Included EndPoints in ProductViewSet:
# GET        /api/products/        Retrieve a list of all products    
# POST        /api/products/        Create a new product    
# GET        /api/products/<id>/    Retrieve a single product by ID    
# PUT        /api/products/<id>/    Update an existing product    
# PATCH        /api/products/<id>/    Partially update a product    
# DELETE    /api/products/<id>/    Delete a product

  1. Add the API URLs to backend/urls.py:

# Importing necessary modules for URL configuration
from django.contrib import admin
from django.urls import path, include

# Defining the URL patterns for the project
urlpatterns = [
    # URL for the Django admin panel
    path('admin/', admin.site.urls),
    # Includes the URLs from the API application
    path('', include('api.urls')),  # Routes requests to the API's URL configuration
]

  1. Register Your Models in admin.py

# Importing Django's admin module
from django.contrib import admin
# Importing the default UserAdmin class for managing users in the admin panel
from django.contrib.auth.admin import UserAdmin
# Importing the custom User model and the Product model
from .models import User, Product

# Customizing the admin panel for the User model
class CustomUserAdmin(UserAdmin):
    list_display = ('id', 'username', 'email', 'first_name', 'last_name', 'is_staff', 'is_active')  
    # Columns displayed
    search_fields = ('username', 'email', 'first_name', 'last_name')  # Enables search functionality
    list_filter = ('is_staff', 'is_active')  # Filters for easier navigation
    ordering = ('id',)  # Default ordering by user ID

# Customizing the admin panel for the Product model
class ProductAdmin(admin.ModelAdmin):
    list_display = ('id', 'name', 'description', 'price', 'user')  # Columns displayed
    search_fields = ('name', 'description')  # Enables search by name or description
    list_filter = ('price',)  # Filter for easier navigation
    ordering = ('id',)  # Default ordering by product ID

# Registering the models in the Django admin panel
admin.site.register(User, CustomUserAdmin)
admin.site.register(Product, ProductAdmin)

  1. Apply the Migrations to the Database:

# Creates migration files for changes in the database models
python manage.py makemigrations  
# Applies the migrations to the database, creating or updating tables as needed
python manage.py migrate

  1. Create a Super User to Access the Admin Interface:

python manage.py createsuperuser

You will be prompted to enter the following details:

  • Username: Enter a unique username (e.g., admin).

  • Email address: Provide an email (optional, but recommended).

  • Password: Enter a strong password (it won’t be displayed while typing).

  • Confirm password: Re-enter the password.

If you forget the password, you can reset it using:

python manage.py changepassword your_username

  1. Run the Backend Server:

python manage.py runserver

  1. Access Admin Interface and Add Records

  • In your browser, type:
http://127.0.0.1:8000/admin
  • Access the Admin Interface using your Super User login.

  • Add a new user record in users table:

IDUSERNAMEEMAIL_ADDRESS
1admin
2leo
  • Add some records in products table:
IDNAMEDESCRIPTIONPRICEUSER
1Wireless HeadphonesHigh-quality Bluetooth noise-canceling headphones.99.99Admin
2Gaming LaptopPowerful laptop with an RTX 3060 and 16GB RAM.1299.99Admin
3Smartphone5G-enabled smartphone with a 64MP camera.699.99Leo
4Mechanical KeyboardRGB backlit mechanical keyboard with blue switches.79.99Leo

  1. Test the API

  • Create Autorization Token Request in Postman:

GET

http://localhost:8000/api/token/

Headers Tab:

KEYVALUE
Content-Typeapplication/json

Body Tab → raw:

{
  "username": "admin",
  "password": "admin_password"
}

Copy the output token.

  • Create Products Requests in Postman:

Headers Tab (All Requests):

KEYVALUE
Content-Typeapplication/json
AuthorizationToken [output_token]

Body Tab → raw (Request 3 - POST):

{
  "name": "Notebook Gamer",
  "description": "RTX 4060, 16GB RAM",
  "price": 8500.00,
  "user": 2
}

Body Tab → raw (Request 4 - PUT):

{
    "name": "Wireless Headphone",
    "description": "High-quality Bluetooth noise-canceling headphones.",
    "price": "199.99",
    "user": 1
}

Body Tab → raw (Request 5 - PATCH):

{
  "price": 149.00
}
  • Test All Products Requests

Run the requests in this sequence: 1, 2, 3, 4, 5, 6, 3.


Conclusion

In this article, we set up the backend of a full-stack application using React +Django + MySQL. The main steps covered include:

  • Setting up a virtual environment and installing dependencies for the Backend.

  • Creating a Django project and configuring MySQL as the database.

  • Implementing user authentication with Django's authentication system and REST Framework.

  • Building a Product model with CRUD operations.

  • Creating serializers to convert model instances into JSON format.

  • Developing API views using Django REST Framework.

  • Configuring CORS to allow communication with the frontend.

  • Testing API endpoints using Postman.

With the API ready, the next step is to develop the frontend using React. The frontend will interact with the backend through API requests, allowing users to register, authenticate, and manage products.