Django CRUD from scratch with Validation Message

Django CRUD
Spread the love

Django is a Python-based free and open-source web framework that follows the model–template–views architectural pattern. In this tutorial, I will show you how to do CRUD operations in Django from scratch. Also, I will show you, how to show validation errors and messages. Before jumping this tutorial, you have to install python and Django on your machine. Read this blog to install a Django project as well as set up your environment.

Prequisite : Start a Django project from scratch and print hello world

I assume you have successfully installed a fresh Django project. Well, now you have to open a virtual environment. To to that run this command pipenv shell. Well, now your terminal redirects to the virtual environment like this.

  ((mysite) ) shahin@shahin-bhai:~/Desktop/Python/DJ/mysite$

Well, now create an app using this command. python manage.py startapp crud. Hit this command in your virtual environment, then it will create a new folder according to your given name. Inside the app, you can see a couple of files and folders like the below image.

Well, after creating an app then you have to register it in your project’s settings.py file.


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

Well, now create a new file that name is urls.py. Well, inside the urls.py file you have to define your URLs/route according to your need. I defined a couple of URLs that are related to the CRUD operation.

from django.urls import path

from . import views

urlpatterns = [
    path('', views.index, name='crud.index'),
    path('/create', views.create, name='crud.create'),
    path('/store', views.store, name='crud.store'),
    path('/view/<int:id>', views.view, name='crud.view'),
    path('/delete/<int:id>', views.delete, name='crud.delete'),
    path('/edit/<int:id>', views.edit, name='crud.edit'),
    path('/update/<int:id>', views.update, name='crud.update'),
]

Well, now bind this urls.py file with the main urls.py file. Go to the project’s urls.py file and modify your code like below.


from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('crud.urls')),
]

Now create a model in the models.py file. Your model will be like this.

class ToDo(models.Model):
    title = models.CharField(max_length=200)
    image = models.ImageField(null=True)
    status = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.title

Now run those commands in your virtual environment to create a database according to the model.

python manage.py makemigrations
python manage.py migrate

Well, you can see the crud/urls.py file I have imported the view file. In the view file, we have to write our method. Let’s see the code of the view file.

from django.http import HttpResponse
from django.shortcuts import render, redirect
from django.http import HttpResponse
from django.contrib import messages
from crud.models import ToDo


def index(request):
    data = {
        "todos": ToDo.objects.order_by('-created_at').all()
    }
    return render(request, 'crud/index.html', data)


def create(request):
    return render(request, 'crud/create.html')


def store(request):
    if request.method == "POST":
        title = request.POST['title']
        if not title:
            messages.warning(request, 'Field Must Not Be empty!')
            return redirect('crud.create')

        is_active = request.POST['is_active']
        todo = ToDo(title=title, status=is_active)
        todo.save()
        messages.success(request, 'Form submission successful')
        return redirect('crud.index')


def view(request, id):
    todo = ToDo.objects.get(id=id)
    return render(request, 'crud/view.html', {"todo": todo})


def delete(request, id):
    ToDo.objects.get(id=id).delete()
    messages.info(request, 'Data Deleted successful')
    return redirect('crud.index')


def edit(request, id):
    todo = ToDo.objects.get(id=id)
    return render(request, 'crud/edit.html', {"todo": todo})


def update(request, id):
    todo = ToDo.objects.get(id=id)
    todo.title = request.POST['title']
    todo.status = request.POST['is_active']
    todo.save()
    messages.success(request, 'Data Updated successful')

    return redirect('crud.view', id)

Well, you can see a bunch of code in the view file. All functions are mapped with the URLs which I have defined in the crud/urls.py file. Now create a templates folder inside your crud folder, inside the templates folder create another folder whose name will be according to your app name. Well inside the folder, you have to create a couple of files. Create the files and copy the code below.

base.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet">
    <title>{% block title %}
    <style>
        .success{
            color: green;
        }
    </style>
    {% endblock  %}</title>
</head>
<body>

    <div class="container mt-5">
        <h2 class="text-center">Django CRUD</h2>
        <hr>
        <div class="row justify-content-center">
            <div class="col-md-8">
                {% if messages %}
                    {% for message in messages %}
                    <div class="alert alert-{{ message.tags }}" role="alert">
                        {{ message }}
                      </div>
                    {% endfor %}
                {% endif %}
            </div>
        </div>
        <div class="row justify-content-center">
                {% block content %}
          
                {% endblock  %}
        </div>
    </div>
</body>
</html>

index.html

{% extends "crud/base.html" %}

{% block title %}
  All Todo
{% endblock title %}

{% block content %}
<div class="col-md-8">
    <div class="d-flex justify-content-between">
        <div>
            <h2>Manage All Todo</h2>
        </div>
        <div class="align-self-center">
            <a href="{% url 'crud.create' %}" class="btn btn-sm btn-success">Add New Todo</a> 
        </div>
    </div>
    <hr>
    <table class="table table-bordered text-center">
        <tr class="table-heading">
            <th>SL</th>
            <th>Title</th>
            <th>Image</th>
            <th>Status</th>
            <th>Time</th>
            <th>Actions</th>
        </tr>
        {% for todo in todos %}  
        <tr>
            <td>{{ forloop.counter }}</td>
            <td>{{ todo.title }}</td>
            <td><img src="" alt=""></td>
            <td>{{ todo.status }}</td>
            <td>{{ todo.created_at }}</td>
            <td>
                <a href="{% url 'crud.view' todo.id %}" class="btn btn-sm btn-success">View</a>
                <a href="{% url 'crud.edit' todo.id %}"  class="btn btn-sm btn-info">Edit</a>
                <a href="{% url 'crud.delete' todo.id %}" class="btn btn-sm btn-danger">Delete</a>
            </td>
        </tr>
        {% endfor %}
    </table>
</div>
{% endblock content %}

create.html

{% extends "crud/base.html" %}

{% block title %}
  Create
{% endblock title %}

{% block content %}
<div class="col-md-8">
    <div class="d-flex justify-content-between">
        <div>
            <h2>Create a Todo</h2>
        </div>
        <div class="align-self-center">
            <a href="{% url 'crud.index'%}" class="btn btn-sm btn-success">Back</a> 
        </div>
    </div>
    <hr>
    <form action="{% url 'crud.store'%}" method="post">
        {% csrf_token %}
        <div class="form-group my-3">
            <input type="text" class="form-control" name="title" placeholder="Enter New title">
        </div>
        <div class="form-group my-3">
            <input type="file" class="form-control" name="image">
        </div>
        <div class="form-group my-3">
            <label for="">Active</label>
            <input type="radio"  name="is_active" value="1">
            <label for="">In Active</label>
            <input type="radio" name="is_active" value="0">
        </div>
        <div class="my-3">
            <button class="btn btn-success btn-block">Submit</button>
        </div>
    </form>
</div>
{% endblock content %}

view.html

{% extends "crud/base.html" %}

{% block title %}
Todo | {{ todo }}
{% endblock title %}

{% block content %}
<div class="col-md-8">
    <div class="d-flex justify-content-between">
        <div>
            <h2>Single Todo</h2>
        </div>
        <div class="align-self-center">
            <a href="{% url 'crud.index' %}" class="btn btn-sm btn-success">Back</a> 
        </div>
    </div>
    <hr>
    <table class="table table-bordered text-center">
        <tr>
            <th>Title</th>
            <td>{{ todo.title }}</td>
        </tr>
        <tr>
            <th>Image</th>
            <td>{{ todo.title }}</td>
        </tr>

        <tr>
            <th>Status</th>
            <td>{{ todo.status }}</td>
        </tr>
        <tr>
            <th>Created At</th>
            <td>{{ todo.created_at }}</td>
        </tr>
    </table>
</div>
{% endblock content %}

edit.html

{% extends "crud/base.html" %}

{% block title %}
  Edit | {{ todo }}
{% endblock title %}

{% block content %}
<div class="col-md-8">
    <div class="d-flex justify-content-between">
        <div>
            <h2>Edit a Todo</h2>
        </div>
        <div class="align-self-center">
            <a href="{% url 'crud.index'%}" class="btn btn-sm btn-success">Back</a> 
        </div>
    </div>
    <hr>
    <form action="{% url 'crud.update' todo.id%}" method="post">
        {% csrf_token %}
        <div class="form-group my-3">
            <input type="text" class="form-control" name="title" placeholder="Enter New title" value="{{ todo.title }}">
        </div>
        <div class="form-group my-3">
            <input type="file" class="form-control" name="image">
        </div>
        <div class="form-group my-3">
            <label for="">Active</label>
            <input type="radio"  name="is_active" value="1" {% if todo.status %}
            checked
            {% endif %}>
             | 
            <label for="">In Active</label>
            <input type="radio" name="is_active" value="0" {% if not todo.status %}
            checked
          {% endif %}>
        </div>
        <div class="my-3">
            <button class="btn btn-success btn-block">Update</button>
        </div>
    </form>
</div>
{% endblock content %}

Hit this command python manage.py runserver

Django CRUD
Django CRUD

Spread the love

About Anisur Rahman Shahin

Hello. My name is Shahin. I'm a tech enthusiast guy. Personally, I’m an Optimistic and always in hurry kinda person. I'm a freelance web developer. I am working at Zakir Soft as Laravel Developer. My Portfolio website: https://tutspack.com

View all posts by Anisur Rahman Shahin →

Leave a Reply

Your email address will not be published.