Python Tutorial - Python Django CRUD Operation with PostgreSQL Database - StudentCRUD
--- download and install python ---
https://www.python.org/downloads/
and install the "python-3.12.2-amd64.exe" file
--- install django in cmd ---
pip install django
1. Create a Project
django-admin startproject student_project
2. Create an App
cd student_project
python manage.py startapp student_crud
3. Project Structure
code .
Now you can open terminal in VSCode. then run command:
python manage.py runserver
# Create files as below structure.
• student_project
|
+---• student_crud (app folder)
| |
| +--• migrations (includes files related to migrations)
| |
| +--• templates
| | |--• student_crud
| | | |--base.html
| | | |--student_form.html
| | | |--student_list.html
| |
| |--models.py
| |--forms.py
| |--urls.py
| |--views.py
|
+---• student_project (project folder)
| |
| |--settings.py
| |--urls.py
4. Register your project in settings.py
student_project->settings.py
add inside the
INSTALLED_APPS = [
........
........
'student_crud'
]
5. Database Setup
->Open pgAdmin for accessing the PostgreSQL Database.
->Create a database StudentCRUD in PostgreSQL,
and configure into the settings.py file of django project.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'StudentCRUD',
'USER': 'postgres',
'PASSWORD': 'admin@123',
'HOST': 'localhost',
}
}
Then Run :
python manage.py migrate
Note : If you are getting error like below then:
Traceback (most recent call last):
File "C:\Users\Administrator\AppData\Local\Programs\Python\Python312\Lib\site-packages\django\db\backends\postgresql\base.py", line 25, in <module>
import psycopg as Database
ModuleNotFoundError: No module named 'psycopg'
...........................
....................
Run for Python3 users:
pip install psycopg
pip install psycopg2
Now you can run the upgrade pip:
python.exe -m pip install --upgrade pip
6. Create Models
goto student_crud -> models.py
from django.db import models
# Create your models here.
class Section(models.Model):
title = models.CharField(max_length=50)
def __str__(self):
return self.title
class Student(models.Model):
fullname = models.CharField(max_length=100)
std_reg = models.CharField(max_length=3)
mobile = models.CharField(max_length=15)
section = models.ForeignKey(Section, on_delete=models.CASCADE)
7. now run migrations
python manage.py makemigrations student_crud
8. now run sqlmigrate
python manage.py sqlmigrate student_crud 0001
9. now run migrate
python manage.py migrate
10. create goto student_crud -> views.py
from django.shortcuts import render, redirect
from .forms import StudentForm
from .models import Student
# Create your views here.
def student_list(request):
context = {'student_list':Student.objects.all()}
return render(request,"student_crud/student_list.html",context)
def student_form(request,id=0):
if request.method == "GET":
if id==0:
form = StudentForm()
else:
student = Student.objects.get(pk=id)
form = StudentForm(instance=student)
return render(request,"student_crud/student_form.html",{'form':form})
else:
if id == 0:
form = StudentForm(request.POST)
else :
student = Student.objects.get(pk=id)
form = StudentForm(request.POST,instance = student)
if form.is_valid():
form.save()
return redirect('/student/list/')
def student_delete(request,id):
student = Student.objects.get(pk=id)
student.delete()
return redirect('/student/list/')
11. add lines in student_project -> urls.py (inside the student_project)
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('student/', include("student_crud.urls")),
]
12. create student_crud -> urls.py file inside the student_crud folder
from django.urls import path,include
from . import views
urlpatterns = [
path('', views.student_form),
path('list/', views.student_list),
path('',views.student_form,name='student_insert'), # get and post request for insert operation
path('<int:id>/',views.student_form,name='student_update'), # get and post request for update operation
path('list/',views.student_list,name='student_list'), # get request for retrieve and display records
path('delete/<int:id>',views.student_delete,name='student_delete'), # get and post request for update operation
]
13. create templates folder inside the app folder (i.e student_crud)
templates -> student_crud
14. Create Files
base.html
student_list.html
student_form.html
15. in base.html
<!DOCTYPE html>
<html>
<head>
<title>Student Crud</title>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha512-DTOQO9RWCH3ppGqcWaEA1BIZOC6xxalwEsw9c2QQeAIftl+Vegovlnee1c9QX4TctnWMn13TZye+giMm8e2LwA==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.min.js" integrity="sha384-BBtl+eGJRgqQAUMxJ7pMwbEyER4l1g+O15P+16Ep7Q9Q+zqX6gSbd85u4mG4QzX+" crossorigin="anonymous"></script>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-8 offset-2">
{% block content %}
{% endblock content %}
</div>
</div>
</div>
</body>
</html>
16. in student_list.html
{% extends 'student_crud/base.html' %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-8 offset-2">
<table class="table table-borderless">
<thead class="border-bottom font-weight-bold">
<tr>
<td>Full Name</td>
<td>Mobile</td>
<td>Section</td>
<td>Action</td>
</tr>
</thead>
<tbody>
{% for student in student_list %}
<tr>
<td>{{student.fullname}}</td>
<td>{{student.mobile}}</td>
<td>{{student.section}}</td>
<td>
<a href="{% url 'student_update' student.id %}" class="btn text-secondary px-0">
<i class="fas fa-edit"></i> Edit
</a>
<a href="{% url 'student_insert' %}" class="btn btn-outline-success">
<i class="fas fa-plus"></i> Add
</a>
<form action="{% url 'student_delete' student.id %}" method="post" class="d-inline" >
{% csrf_token %}
<button type="submit" class="btn">
<i class="fas fa-trash-alt text-danger"></i>
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock content %}
17. in student_form.html
{% extends 'student_crud/base.html' %}
{% load crispy_forms_tags %}
{% block content %}
<form action="" method="post" autocomplete="off">
{% csrf_token %}
{{form.fullname|as_crispy_field}}
{{form.mobile|as_crispy_field}}
<div class="row">
<div class="col-md-6">
{{form.std_reg|as_crispy_field}}
</div>
<div class="col-md-6">
{{form.section|as_crispy_field}}
</div>
</div>
<div class="container">
<div class="row">
<div class="col-md-8">
<button type="submit" class="btn btn-success btn-block btn-lg"><i class="fa-solid fa-database"></i> Submit</button>
</div>
<div class="col-md-3">
<a href="{% url 'student_list' %}" class="btn btn-secondary btn-block btn-lg"><i class="fas fa-stream"></i> Back to List</a>
</div>
</div>
</div>
</form>
{% endblock content %}
18. create new file inside student_crud (app folder)
forms.py
add the below lines in forms.py
from django import forms
from .models import Student
class StudentForm(forms.ModelForm):
class Meta:
model = Student
fields = ('fullname','mobile','std_reg','section')
labels = {
'fullname':'Full Name',
'std_reg':'Student Registration'
}
def __init__(self,*args, **kwargs):
super(StudentForm,self).__init__(*args, **kwargs)
self.fields['section'].empty_label = "Select"
self.fields['std_reg'].required = False
19. for the best design of the form we can use crispy forms and crispy bootstrap.
pip install django-crispy-forms
pip install crispy-bootstrap4
20. Add crispy-forms in settings.py
student_project->settings.py
add inside the
INSTALLED_APPS = [
........
........
'crispy_forms',
'crispy_bootstrap4'
]
And then at the bottom of the page of settings.py
CRISPY_ALLOWED_TEMPLATE_PACKS = "bootstrap4"
CRISPY_TEMPLATE_PACK = "bootstrap4"
21. student_list.html page.
{% extends 'student_crud/base.html' %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-8 offset-2">
<table class="table table-borderless">
<thead class="border-bottom font-weight-bold">
<tr>
<td>Full Name</td>
<td>Mobile</td>
<td>Section</td>
<td>Action</td>
</tr>
</thead>
<tbody>
{% for student in student_list %}
<tr>
<td>{{student.fullname}}</td>
<td>{{student.mobile}}</td>
<td>{{student.section}}</td>
<td>
<a href="{% url 'student_update' student.id %}" class="btn text-secondary px-0">
<i class="fas fa-edit"></i> Edit
</a>
<a href="{% url 'student_insert' %}" class="btn btn-outline-success">
<i class="fas fa-plus"></i> Add
</a>
<form action="{% url 'student_delete' student.id %}" method="post" class="d-inline" >
{% csrf_token %}
<button type="submit" class="btn">
<i class="fas fa-trash-alt text-danger"></i>
</button>
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endblock content %}
22. Open Browser and run
http://127.0.0.1:8000/student/
and
http://127.0.0.1:8000/student/list/