Django 3 tutorial and CRUD example with MySQL and Bootstrap

Keywords: Django MySQL Database Python

Catalog

Django 3 features

Precondition

Django 3 tutorial, step 1: create MySQL database

Django 3 tutorial, step 2 - initializing a new virtual environment

Django 3 tutorial, step 3 - install Django and MySQL client

Django 3 tutorial, step 4 - initializing a new project

Django 3 tutorial, step 5 - install Django widget twiaks

Django 3 tutorial, step 6 - create administrator user

Django 3 tutorial, step 7 - create Django application

Django 3 tutorial, step 8 - create model

Django 3 tutorial, step 9 - create form

Django 3 tutorial, step 10 - create views

Django 3 tutorial, step 11 - create template

Django 3 tutorial, step 12 - create URL

Django 3 tutorial, step 13 - running the local development server

conclusion

Django 3 has been released with full asynchronous support! In this tutorial, we'll step through the examples to demonstrate how to create CRUD applications. We'll see how to configure the MySQL database, enable the management interface, and create the django view.

We will use Bootstrap 4 for styling.

You will learn how to:

  • Implement CRUD operation
  • Configure and access MySQL database
  • Create Django views, templates, and URL s
  • Using Bootstrap 4 to style the UI

Django 3 features

Django 3 has many new features, such as:

  • MariaDB support: Django now officially supports MariaDB 10.1 +. You can use MariaDB through MySQL backend
  • ASGI supports asynchronous programming
  • Django 3.0 provides support for running as an ASGI application, making Django fully asynchronous
  • Exclusion constraints on PostgreSQL: Django 3.0 added a new exclusion constraint class, which added exclusion constraints on PostgreSQL, etc.

Precondition

Let's start with the prerequisites for this tutorial. In order to follow this tutorial step by step, you need to meet some requirements, such as:

  • Python Basics
  • Working knowledge of Django (django-admin.py and manage.py)
  • The latest version of Python 3 is installed on your system (the latest version is 3.7)
  • MySQL database is installed on the system

We'll use pip and venv, which are bundled as modules in the latest version of Python, so unless you're using an older version, you don't actually need to install them.

If you are ready, let's start!

Django 3 tutorial, step 1: create MySQL database

In this step, we will create a mysql database to store our application data.

Open a new command line interface and run mysql client as follows:

$ mysql -u root -p

You will be prompted for a MySQL password, Enter the password, and press Enter.

Next, create the database using the following SQL statement:

mysql> create database mydb;

We now have an empty mysql database!

Django 3 tutorial, step 2 - initializing a new virtual environment

In this step, we will initialize a new virtual environment to separate system wide packages to install our project packages.

Go back to your command line interface and run the following command:

$ python3 -m venv .env

Next, activate your virtual environment using the following command:

$ source .env/bin/activate

At this point in this tutorial, we have a mysql database for saving data and created a virtual environment for installing project packages.

Django 3 tutorial, step 3 - install Django and MySQL client

In this step, we will use pip to install django and mysql clients from PyPI in the active virtual environment.

Go back to your command line interface and run the following command to install the django package:

$ pip install django

At the time of writing this tutorial, django-3.0.2 was installed.

You also need to use the pip command to install mysql client for Python:

$ pip install mysqlclient

Django 3 tutorial, step 4 - initializing a new project

In this step, we will use django admin to initialize a new django project.

Go back to your command line interface and run the following command:

$ django-admin startproject djangoCrudExample

Next, open the settings.py file and update the database settings to configure the mydb database:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql', 
        'NAME': 'mydb',
        'USER': 'root',
        'PASSWORD': '<YOUR_DB_PASSWORD>',
        'HOST': 'localhost',   
        'PORT': '3306',
    }    
}

Next, use the following command to migrate the database:

$ cd djangoCrudExample
$ python3 manage.py migrate

You will get similar output:

Operations to perform:
  Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  Applying admin.0002_logentry_remove_auto_add... OK
  Applying admin.0003_logentry_add_action_flag_choices... OK
  Applying contenttypes.0002_remove_content_type_name... OK
  Applying auth.0002_alter_permission_name_max_length... OK
  Applying auth.0003_alter_user_email_max_length... OK
  Applying auth.0004_alter_user_username_opts... OK
  Applying auth.0005_alter_user_last_login_null... OK
  Applying auth.0006_require_contenttypes_0002... OK
  Applying auth.0007_alter_validators_add_error_messages... OK
  Applying auth.0008_alter_user_username_max_length... OK
  Applying auth.0009_alter_user_last_name_max_length... OK
  Applying auth.0010_alter_group_name_max_length... OK
  Applying auth.0011_update_proxy_permissions... OK
  Applying sessions.0001_initial... OK

This just applies a set of built-in django migrations to create some necessary database tables or django work.

Django 3 tutorial, step 5 - install Django widget twiaks

In this step, we will install Django widget twiaks in a virtual environment. Go back to your command line interface and run the following command:

$ pip insll django-widget-tweaks

Next, open the settings.py file and add the application to the installed application:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'widget_tweaks'
]

Django 3 tutorial, step 6 - create administrator user

In this step, we will create an administrator user that will allow us to access the administration interface of the application using the following commands:

$ python manage.py createsuperuser

Provide the required user name, email and password when prompted:

Username (leave blank to use 'ahmed'): 
Email address: ahmed@gmail.com
Password: 
Password (again): 
Superuser created successfully.

Django 3 tutorial, step 7 - create Django application

In this step, we will create a django application.

Go back to your command line interface and run the following command:

$ python manage.py startapp crudapp

Next, you need to add it to the settings.py file as follows:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'widget_tweaks',
    'crudapp'
]

Django 3 tutorial, step 8 - create model

In this step, we will create a database model for storing contacts.

Open the crudapp/models.py file and add the following code:

from django.db import models

class Contact(models.Model):
    firstName = models.CharField("First name", max_length=255, blank = True, null = True)
    lastName = models.CharField("Last name", max_length=255, blank = True, null = True)
    email = models.EmailField()
    phone = models.CharField(max_length=20, blank = True, null = True)
    address = models.TextField(blank=True, null=True)
    description = models.TextField(blank=True, null=True)
    createdAt = models.DateTimeField("Created At", auto_now_add=True)
    
    def __str__(self):
        return self.firstName

After you create these models, you need to create the migration using the following command:

$ python manage.py makemigrations

You should get similar output:

crudapp/migrations/0001_initial.py
  - Create model Contact

Next, you need to migrate the database using the following command:

$ python manage.py migrate

You should get similar output:

Applying crudapp.0001_initial... OK

Django 3 tutorial, step 9 - create form

In this step, we will create a form for creating contacts.

In the crudapp folder, create a forms.py file and add the following code:

from django import forms
from .models import Contact

class ContactForm(forms.ModelForm):
    class Meta:
        model = Contact
        fields = "__all__"

We import the Contact model from the models.py file. We created a class named ContactForm, inherited Django's ModelForm from django.forms package, and specified the model we want to use. We also specify that all fields in the Contact model will be used. This will enable us to display these fields in the template.

Django 3 tutorial, step 10 - create views

In this step, we will create a view to perform CRUD operations.

Open the crudapp/views.py file and add:

from django.shortcuts import render, redirect, get_object_or_404
from .models import Contact
from .forms import ContactForm
from django.views.generic import ListView, DetailView

Next, add:

class IndexView(ListView):
    template_name = 'crudapp/index.html'
    context_object_name = 'contact_list'
    
    def get_queryset(self):
        return Contact.objects.all()

class ContactDetailView(DetailView):
    model = Contact
    template_name = 'crudapp/contact-detail.html'

Next, add:

def create(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('index')
    form = ContactForm()

    return render(request,'crudapp/create.html',{'form': form})

def edit(request, pk, template_name='crudapp/edit.html'):
    contact = get_object_or_404(Contact, pk=pk)
    form = ContactForm(request.POST or None, instance=post)
    if form.is_valid():
        form.save()
        return redirect('index')
    return render(request, template_name, {'form':form})

def delete(request, pk, template_name='crudapp/confirm_delete.html'):
    contact = get_object_or_404(Contact, pk=pk)
    if request.method=='POST':
        contact.delete()
        return redirect('index')
    return render(request, template_name, {'object':contact})

Django 3 tutorial, step 11 - create template

Open the settings.py file and add os.path.join (base \ dir, 'TEMPLATES') to the TEMPLATES array:

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

This tells django to find the template in the template folder.

Next, in the crudapp folder, create a template folder:

$ mkdir templates

Next, in the Templates folder, create the following files:

  • base.html
  • Confirm_delete.html
  • edit.html
  • index.html
  • create.html
  • contact-detail.html

Run the following command from the root of the project:

$ mkdir templates
$ cd templates
$ mkdir crudapp
$ touch crudapp/base.html
$ touch crudapp/confirm_delete.html
$ touch crudapp/edit.html
$ touch crudapp/index.html
$ touch crudapp/create.html
$ touch crudapp/contact-detail.html

Open crudapp/templates/base.html file and add:

<!DOCTYPE html>
<html>
<head>
 <title>Django 3 CRUD Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" 

href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
</head>
<body>
{% block content %}
{% endblock %}
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" 

integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" 

crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" 

integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" 

crossorigin="anonymous"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
</body>
</html>

Next, open the crudapp/templates/index.html file, and add:

{% extends 'crudapp/base.html' %}
{% block content %}
<div class="container-fluid">
    <div class="row">
        <div class="col-md-1 col-xs-1 col-sm-1"></div>
        <div class="col-md-10 col-xs-10 col-sm-10">
            <h3 class="round3" style="text-align:center;">Contacts</h3>
        </div>
        <div class="col-md-1 col-xs-1 col-sm-1"></div>
    </div>
    <div class="row">
        <div class="col-md-10 col-xs-10 col-sm-10"></div>
        <div class="col-md-2 col-xs-1 col-sm-1">
            <br />
            <a href="{% url 'create' %}">
                <button type="button" class="btn btn-success">
                    <span class="glyphicon glyphicon-plus"></span>
                </button>
            </a>
        </div>
    </div>
    <br />
    {% for contact in contact_list %}
    <div class="row">
        <div class="col-md-1 col-xs-1 col-sm-1"></div>
        <div class="col-md-7 col-xs-7 col-sm-7">
            <ul class="list-group">

                <li class="list-group-item ">
                    <a href="{% url 'detail' contact.pk %}"> {{ contact.firstName }} 
                    {{contact.lastName}} </a> <span class="badge"></span>
                </li>
            </ul>
            <br>
        </div>
        <div class="col-md-1 col-xs-1 col-sm-1">
            <a href="{% url 'detail' contact.pk %}">
                <button type="button" class="btn btn-info">
                    <span class="glyphicon glyphicon-open"></span>
                </button>
            </a>
        </div>
        <div class="col-md-1">
            <a href="{% url 'edit' contact.pk %}">
                <button type="button" class="btn btn-info">
                    <span class="glyphicon glyphicon-pencil"></span>
                </button>
            </a>
        </div>
        <div class="col-md-1">
            <a href="{% url 'delete' contact.pk %}">
                <button type="button" class="btn btn-danger">
                    <span class="glyphicon glyphicon-trash"></span>
                </button>
            </a>
        </div>
        <div class="col-md-1 col-xs-1 col-sm-1"></div>
    </div>
    {% endfor %}
</div>
{% endblock %}

Next, open the crudapp/templates/create.html file and add:

{% load widget_tweaks %}
<!DOCTYPE html>
<html>

<head>
    <title>Posts</title>
    <meta charset="utf-8">
    <meta name="viewport" 

    content="width=device-width, initial-scale=1">
    <link rel="stylesheet" 

    href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"

        integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" 

        crossorigin="anonymous">
    <style type="text/css">
        <style>
    </style>
    </style>

</head>

<body>

    <div class="container-fluid">
        <div class="row">
            <div class="col-md-1 col-xs-1 col-sm-1"></div>

            <div class="col-md-10 col-xs-10 col-sm-10 ">
                <br />
                <h6 style="text-align:center;">
                    <font color="red"> All fields are required</font>
                </h6>
            </div>
            <div class="col-md-1 col-xs-1 col-sm-1">
            </div>
        </div>
        <div class="row">
            <div class="col-md-1 col-xs-1 col-sm-1"></div>
            <div class="col-md-10 col-xs-10 col-sm-10">
                <form method="post" novalidate>
                    {% csrf_token %}
                    {% for hidden_field in form.hidden_fields %}
                    {{ hidden_field }}
                    {% endfor %}
                    {% for field in form.visible_fields %}
                    <div class="form-group">
                        {{ field.label_tag }}
                        {% render_field field class="form-control" %}
                        {% if field.help_text %}
                        <small class="form-text text-muted">{{ field.help_text }}</small>
                        {% endif %}
                    </div>
                    {% endfor %}
                    <button type="submit" class="btn btn-primary">post</button>
                </form>
                <br>
            </div>
            <div class="col-md-1 col-xs-1 col-sm-1"></div>
        </div>
    </div>
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"

        integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"

        crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"

        integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49"

        crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"

        integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy"

        crossorigin="anonymous"></script>
</body>

</html>

Next, open the crudapp/templates/edit.html file and add:

{% load widget_tweaks %}
<!DOCTYPE html>
<html>

<head>
    <title>Edit Contact</title>
    <meta charset="utf-8">
    <meta name="viewport" 

    content="width=device-width, initial-scale=1">
    <link rel="stylesheet" 

    href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css"

        integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" 

        crossorigin="anonymous">
    <style type="text/css">
        <style>
    </style>
    </style>

</head>

<body>
<div class="container-fluid">
    <div class="row">
        <div class="col-md-1 col-xs-1 col-sm-1"></div>
        <div class="col-md-10 col-xs-10 col-sm-10 ">
            <br />
            <h6 style="text-align:center;">
                <font color="red"> All fields are required</font>
            </h6>
        </div>
        <div class="col-md-1 col-xs-1 col-sm-1">
        </div>
    </div>
    <div class="row">
        <div class="col-md-1 col-xs-1 col-sm-1"></div>
        <div class="col-md-10 col-xs-10 col-sm-10">
            <form method="post" novalidate>
                {% csrf_token %}
                {% for hidden_field in form.hidden_fields %}
                {{ hidden_field }}
                {% endfor %}
                {% for field in form.visible_fields %}
                <div class="form-group">
                    {{ field.label_tag }}
                    {% render_field field class="form-control" %}
                    {% if field.help_text %}
                    <small class="form-text text-muted">{{ field.help_text }}</small>
                    {% endif %}
                </div>
                {% endfor %}
                <button type="submit" class="btn btn-primary">submit</button>
            </form>
            <br>
        </div>
        <div class="col-md-1 col-xs-1 col-sm-1"></div>
    </div>
</div>
<script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" 

integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" 

crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" 

integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" 

crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" 

integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" 

crossorigin="anonymous"></script>
</body>
</html>

Next, open the crudapp/templates/confirm_delete.html file and add:

{% extends 'crudapp/base.html' %}
{% block content %}
<div class="container">
    <div class="row"></div>
    <br />
    <div class="row">
        <div class="col-md-2 col-xs-2 col-sm-2"></div>
        <div class="col-md-10 col-xs-10 col-sm-10">
            <form method="post">
                {% csrf_token %}
                <div class="form-row">
                    <div class="alert alert-warning">
                        Are you sure you want to delete {{ object }}?
                    </div>
                </div>
                <button type="submit" class="btn btn-danger">
                    <span class="glyphicon glyphicon-trash"></span>
                </button>
            </form>
        </div>
    </div>
</div>
{% endblock %}

Django 3 tutorial, step 12 - create URL

In this step, we will create a URL to access our CRUD view.

Go to the urls.py file and update as follows:

from django.contrib import admin
from django.urls import path
from crudapp import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('contacts/', views.IndexView.as_view(), name='index'),
    path('contacts/<int:pk>/', views.ContactDetailView.as_view(), name='detail'),
    path('contacts/edit/<int:pk>/', views.edit, name='edit'),
    path('contacts/create/', views.create, name='create'),
    path('contacts/delete/<int:pk>/', views.delete, name='delete'),
]

Django 3 tutorial, step 13 - running the local development server

In this step, we will run the local development server to run our application without deploying it to the network.

Go back to your command line interface and run the following command:

$ python manage.py runserver

Next, use your web browser to go to the http://localhost:8000 /.

conclusion

In this Django 3 tutorial, we initialize a new Django project, create and migrate MySQL database, and build a simple CRUD interface.

69 original articles published, 133 praised, 440000 visitors+
His message board follow

Posted by envexlabs on Sat, 08 Feb 2020 02:17:36 -0800