Learn how to create and manage CRUD operations in Django with this easy-to-follow guide. Perfect for beginners looking to build web applications.
Creating a CRUD (Create, Read, Update, Delete) application is a fundamental skill in web development. Django, a powerful web framework, makes this process easy and efficient. In this tutorial, you'll learn how to create a complete CRUD application using Django. This guide is perfect for beginners who want to understand how to manage data in web applications. With clear steps and practical examples, you'll be able to set up your own CRUD app in no time.
Prerequisites
Before we dive in, make sure you have a basic understanding of Django and web development. You'll need the following tools and libraries installed on your machine:
- Python (version 3.6 or higher)
- Django (version 3.0 or higher)
- A text editor or IDE (such as VS Code or PyCharm)
- Basic knowledge of HTML and CSS
Setting Up the Development Environment
Installing Django
Before starting, ensure you have Python installed. You can install Django using pip:
pip install django
Creating a new Django project
Create a new Django project using the following command:
django-admin startproject crudoperation
Setting up the project structure
Navigate into your project directory:
cd crudoperation
Create a Django App
Create a new app within your project:
python manage.py startapp myapp
Adding the app to the project
In crudoperation/settings.py
, add myapp
to the INSTALLED_APPS
list:
INSTALLED_APPS = [ 'myapp', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
Creating the ToDo App
Create Models
In myapp/models.py
, Create models with fields that you want to manage through CRUD operations. For this example, let’s use a Book
model:
from django.db import models class Book(models.Model): title = models.CharField(max_length=200) author = models.CharField(max_length=200) description = models.TextField(default='') def __str__(self): return self.title
Create Forms
In myapp, create a new file named forms.py for the CRUD model and add the following function:
from django import forms from .models import Book class BookForm(forms.ModelForm): class Meta: model = Book fields = ['title', 'author', 'description'] widgets = { 'title': forms.TextInput(attrs={ 'class': 'form-input mt-1 block w-full rounded-md border-2 p-2 border-gray-300 shadow-sm', 'placeholder': 'Enter the book title' }), 'author': forms.TextInput(attrs={ 'class': 'form-input mt-1 block w-full rounded-md border-2 p-2 border-gray-300 shadow-sm', 'placeholder': 'Enter the author name' }), 'description': forms.Textarea(attrs={ 'class': 'form-textarea resize-none mt-1 block w-full rounded-md border-2 p-2 border-gray-300 shadow-sm', 'rows': 4, 'placeholder': 'Enter a brief description of the book' }), }
Create Views
Next, we’ll create views for creating, updating, and deleting Book items. Open myapp/views.py
and add the following:
from django.shortcuts import render, redirect, get_object_or_404 from django.contrib import messages from django.http import JsonResponse from .models import Book from .forms import BookForm def create_book(request): if request.method == 'POST': form = BookForm(request.POST) if form.is_valid(): form.save() return JsonResponse({'success': True}) else: return JsonResponse({'success': False, 'errors': form.errors}) return JsonResponse({'success': False}) def edit_book(request, book_id): book = get_object_or_404(Book, id=book_id) if request.method == 'POST': form = BookForm(request.POST, instance=book) if form.is_valid(): form.save() messages.success(request, 'Book updated successfully.') return redirect('book_list') else: form = BookForm(instance=book) return render(request, 'book_form.html', {'form': form, 'is_edit': True}) def delete_book(request, book_id): book = get_object_or_404(Book, id=book_id) book.delete() return redirect('book_list') def book_list(request): books = Book.objects.all() form = BookForm() return render(request, 'book_list.html', {'books': books, 'form': form})
Set Up URL Routing
Add a URL pattern for your view. In myapp/urls.py (create this file if it doesn't exist), add:
from django.urls import path from . import views urlpatterns = [ path('books/', views.book_list, name='book_list'), path('book/create/', views.create_book, name='create_book'), path('book/<int:book_id>/edit/', views.edit_book, name='edit_book'), path('book/<int:book_id>/delete/', views.delete_book, name='delete_book'), ]
Include the app's URLs in your project's URL configuration. Open crudoperation/urls.py and include the CRUD app URLs:
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('', include('myapp.urls')), ]
Create Templates
Create a templates directory within the CRUD app and then create base.html
, book_list.html
and book_form.html
inside this directory.
Base Template (base.html):
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Django CRUD with Tailwind CSS</title> <script src="https://cdn.tailwindcss.com"></script> </head> <body class="bg-gray-100"> {% block content %}{% endblock %} <script> document.addEventListener('DOMContentLoaded', function () { const addBookBtn = document.getElementById('addBookBtn'); const addBookModal = document.getElementById('addBookModal'); addBookBtn.addEventListener('click', function () { addBookModal.classList.remove('hidden'); }); document.querySelectorAll('.cancelButton').forEach(button => { button.addEventListener('click', function () { addBookModal.classList.add('hidden'); }); }); const bookForm = document.getElementById('bookForm'); bookForm.addEventListener('submit', function (e) { e.preventDefault(); const formData = new FormData(bookForm); fetch(bookForm.action, { method: 'POST', body: formData, headers: { 'X-CSRFToken': formData.get('csrfmiddlewaretoken') } }) .then(response => response.json()) .then(data => { if (data.success) { location.reload(); } else { console.error('Error:', data.errors); } }) .catch(error => console.error('Error:', error)); }); }); </script> </body> </html>
Book List Template (book_list.html):
{% extends 'base.html' %} {% block content %} <div class="container mx-auto mt-10"> <h1 class="text-4xl font-extrabold text-gray-900 mb-8">List of Python Books</h1> <button id="addBookBtn" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-lg mb-6"> Add Book </button> <div id="addBookModal" class="hidden fixed inset-0 bg-gray-800 bg-opacity-75 flex justify-center items-center"> <div class="bg-white rounded-lg overflow-hidden shadow-xl w-full max-w-lg"> <div class="px-6 py-4"> <h2 class="text-xl font-bold mb-4">Add Book</h2> <form id="bookForm" action="{% url 'create_book' %}" method="POST"> {% csrf_token %} <div class="form-group"> <label for="{{ form.title.id_for_label }}" class="block text-gray-700 font-semibold mb-2">Title</label> {{ form.title }} </div> <div class="form-group"> <label for="{{ form.author.id_for_label }}" class="block text-gray-700 font-semibold mb-2">Author</label> {{ form.author }} </div> <div class="form-group"> <label for="{{ form.description.id_for_label }}" class="block text-gray-700 font-semibold mb-2">Description</label> {{ form.description }} </div> <div class="flex justify-between mt-6"> <button type="button" class="cancelButton bg-gray-500 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg"> Cancel </button> <button type="submit" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-lg"> Save </button> </div> </form> </div> </div> </div> <table class="min-w-full bg-white shadow-md rounded-lg overflow-hidden"> <thead class="bg-gray-800 text-white"> <tr> <th class="w-1/3 text-left py-3 px-4 uppercase font-semibold text-sm">Title</th> <th class="w-1/3 text-left py-3 px-4 uppercase font-semibold text-sm">Author</th> <th class="text-left py-3 px-4 uppercase font-semibold text-sm">Actions</th> </tr> </thead> <tbody class="text-gray-700"> {% for book in books %} <tr> <td class="w-1/3 text-left py-3 px-4">{{ book.title }}</td> <td class="w-1/3 text-left py-3 px-4">{{ book.author }}</td> <td class="flex gap-5 py-3 px-4"> <a href="{% url 'edit_book' book.id %}" class="bg-yellow-500 hover:bg-yellow-600 text-white font-bold py-2 px-4 rounded-lg"> Edit </a> <a href="{% url 'delete_book' book.id %}" class="bg-red-600 hover:bg-red-700 text-white font-bold py-2 px-4 rounded-lg"> Delete </a> </td> </tr> {% endfor %} </tbody> </table> </div> {% endblock %}
Book Form Template (book_form.html):
{% extends 'base.html' %} {% block content %} <div class="container mx-auto mt-10"> <h1 class="text-4xl font-extrabold text-gray-900 mb-8">{{ is_edit|yesno:"Edit Book,Add Book" }}</h1> <div class="max-w-lg mx-auto bg-white shadow-lg rounded-lg overflow-hidden"> <div class="px-6 py-4"> <form id="bookForm" action="{% if is_edit %}{% url 'edit_book' form.instance.id %}{% else %}{% url 'create_book' %}{% endif %}" method="POST" class="space-y-6"> {% csrf_token %} <div class="form-group"> <label for="{{ form.title.id_for_label }}" class="block text-gray-700 font-semibold mb-2">Title</label> {{ form.title }} </div> <div class="form-group"> <label for="{{ form.author.id_for_label }}" class="block text-gray-700 font-semibold mb-2">Author</label> {{ form.author }} </div> <div class="form-group"> <label for="{{ form.description.id_for_label }}" class="block text-gray-700 font-semibold mb-2">Description</label> {{ form.description }} </div> <div class="flex justify-between mt-6"> <a type="button" href="http://127.0.0.1:8000/books/" class="bg-gray-500 hover:bg-gray-600 text-white font-bold py-2 px-4 rounded-lg"> Cancel </a> <button type="submit" class="bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-lg"> Save </button> </div> </form> </div> </div> </div> {% endblock %}
Run Your Server
Run migrations:
python manage.py makemigrations python manage.py migrate
Run the development server:
python manage.py runserver
Open your browser and go to http://127.0.0.1:8000/books to see your CRUD app in action.
Full Crud App Project Structure
crudoperation/ │ ├── myapp/ │ ├── migrations/ │ │ └── __init__.py │ ├── templates/ │ │ ├── base.html │ │ ├── book_form.html │ │ └── book_list.html │ ├── __init__.py │ ├── admin.py │ ├── apps.py │ ├── forms.py │ ├── models.py │ ├── tests.py │ ├── urls.py │ └── views.py │ ├── crudoperation/ │ ├── __init__.py │ ├── asgi.py │ ├── settings.py │ ├── urls.py │ └── wsgi.py │ ├── db.sqlite3 └── manage.py
Conclusion
Implementing CRUD operations in Django is straightforward and efficient, thanks to its robust framework and tools. By following this guide, you can easily set up and manage your data, creating a seamless user experience. With Django’s built-in functionalities and our step-by-step instructions, you can quickly build and maintain web applications that handle data effectively. Start applying these concepts to your projects and see how Django can streamline your development process.
That’s a wrap!
I hope you enjoyed this article
Did you like it? Let me know in the comments below 🔥 and you can support me by buying me a coffee.
And don’t forget to sign up to our email newsletter so you can get useful content like this sent right to your inbox!
Thanks!
Faraz 😊