article

Sunday, April 24, 2022

Python Django Simple CRUD (Create, Read, Update and Delete)

Python Django Simple CRUD (Create, Read, Update and Delete)

Bootstrap 5
https://getbootstrap.com/docs/5.0/getting-started/introduction/
https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css
testdev/urls.py
1
2
3
4
5
6
7
8
//testdev/urls.py
from django.contrib import admin
from django.urls import path, include #add include
  
urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('myapp.urls')), #add this line
]
myapp/urls.py
1
2
3
4
5
6
7
8
9
10
//myapp/urls.py
from django.urls import path
from . import views
urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path('<int:pk>/', views.PostDetailView.as_view(), name='detail'),
    path('edit/<int:pk>/', views.edit, name='edit'),
    path('post/', views.postview, name='post'),
    path('delete/<int:pk>/', views.delete, name='delete'),
]
myapp/views.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
//myapp/views.py
from django.shortcuts import render, redirect, get_object_or_404
from .forms import PostForm
from .models import Post
from django.views.generic import ListView, DetailView
 
class IndexView(ListView):
    template_name='crud/index.html'
    context_object_name = 'post_list'
 
    def get_queryset(self):
        return Post.objects.all()
 
class PostDetailView(DetailView):
    model=Post
    template_name = 'crud/post-detail.html'
 
def postview(request):
    if request.method == 'POST':
        form = PostForm(request.POST)
 
        if form.is_valid():
            form.save()
            return redirect('index')
 
    form = PostForm()
    return render(request,'crud/post.html',{'form': form})
 
def edit(request, pk, template_name='crud/edit.html'):
    post= get_object_or_404(Post, pk=pk)
    form = PostForm(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='crud/confirm_delete.html'):
    post= get_object_or_404(Post, pk=pk)   
    if request.method=='POST':
        post.delete()
        return redirect('index')
    return render(request, template_name, {'object':post})
myapp/models.py
1
2
3
4
5
6
7
8
9
10
//myapp/models.py
from django.db import models
 
# Create your models here.
class Post(models.Model):
    title = models.CharField(max_length=120, help_text='title of message.')
    message = models.TextField(help_text="what's on your mind ...")
  
    def __str__(self):
        return self.title
Make Migrations
Run the commands below to make migrations:
python manage.py makemigrations
python manage.py migrate
C:\my_project_django\testdev>python manage.py makemigrations
C:\my_project_django\testdev>python manage.py migrate
Table Created Check Database table
myapp/forms.py
1
2
3
4
5
6
7
8
//myapp/forms.py
from django import forms
from .models import Post
 
class PostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = "__all__"
myapp/templates/crud/base.html
1
2
3
4
5
6
7
8
9
10
11
12
13
//myapp/templates/crud/base.html
<!DOCTYPE html>
<html>
<head>
<title>CRUD app</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
{% block content %} {% endblock %}
</body>
</html>  
myapp/templates/crud/index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
//myapp/templates/crud/index.html
{% extends 'crud/base.html' %}
 
{% block content %}
<div class="container">
    <div class="row">
        <h1>Python Django CRUD (Create, Read, Update and Delete)</h1>
    </div>
    <div class="row">
        <div class="col-md-12">
            <h2>Post Table
                <a href="{% url 'post' %}"><button type="button" class="btn btn-success">Add New</button></a>
            </h2>
            <table class="table table-bordered table-striped">
                <thead>
                    <th>Title</th>
                    <th>Action</th>
                </thead>
                <tbody>
                    {% for post in post_list %}
                        <tr>
                            <td><a href="{% url 'detail' post.pk %}">{{ post.title }}</a>  <span class="badge"></span></td>
                            <td>
                                <a href="{% url 'detail' post.pk %}"><button type="button" class="btn btn-info">View</button></a> |
                                <a href="{% url 'edit' post.pk %}"><button type="button" class="btn btn-info">Edit</button></a> |
                                <a href="{% url 'delete' post.pk %}"><button type="button" class="btn btn-danger">Delete</button></a>
                            </td>
                        </tr>
                    {% endfor %}   
                </tbody>
            </table>
        </div>
    </div>
</div>
{% endblock %}
we will be using django-widget-tweaks install it https://pypi.org/project/django-widget-tweaks/
pip install django-widget-tweaks
C:\my_project_django\testdev>pip install django-widget-tweaks
open settings.py INSTALLED_APPS section and add widget_tweaks myapp/templates/crud/post.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//myapp/templates/crud/post.html
{% extends 'crud/base.html' %}
 
{% load widget_tweaks %}
 
{% block content %}
<div class="container" style="padding:40px;">
    <div class="row">
        <div class="col-10">
            <h6 style="text-align:center;"><font color="red"> All fields are required</font> </h6>
        </div>
        <div class="col-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">Add New Post</button>
            </form>
        </div>
    </div>
</div>
{% endblock %}
myapp/templates/crud/post-detail.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//myapp/templates/crud/post-detail.html
{% extends 'crud/base.html' %}
 
{% block content %}
<div class="container" style="padding:40px;">
    <div class="row">
        <div class="col-8">
            <p class="h2">{{post.title}}</p>
        </div>
        <div class="col-4">
            <a href="/"><button type="button" class="btn btn-info">Back</button></a> |
            <a href="{% url 'edit' post.pk %}"><button type="button" class="btn btn-info">Edit</button></a> |
            <a href="{% url 'delete' post.pk %}"><button type="button" class="btn btn-danger">Delete</button></a>
        </div>
    </div>
    <div class="row">
        <div class="col-12">
            {{post.message}}
        </div>
    </div>
</div>
{% endblock %}
myapp/templates/crud/edit.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
//myapp/templates/crud/edit.html
{% extends 'crud/base.html' %}
 
{% load widget_tweaks %}
 
{% block content %}
<div class="container" style="padding:40px;">
    <div class="row">
        <div class="col-10">
            <h6 style="text-align:center;"><font color="red"> All fields are required</font> </h6>
        </div>
        <div class="col-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">Update Post</button>
        </form>
        </div>
    </div>
</div>
{% endblock %}
myapp/templates/crud/confirm_delete.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
//myapp/templates/crud/confirm_delete.html
{% extends 'crud/base.html' %}
{% block content %}
<div class="container" style="padding:20px;">
    <div class="row">
        <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">Delete</button>
            </form>
        </div>
    </div>
</div>
{% endblock %}
Register App myapp

devtest/settings.py
1
2
3
4
5
6
7
8
9
10
11
//devtest/settings.py
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'myapp',
    'widget_tweaks',
]
registered post in admin
and login to admin http://127.0.0.1:8000/admin
1
2
3
4
5
6
//myapp/admin.py
from django.contrib import admin
from .models import Post #add this to import the Post model
 
# Register your models here.
admin.site.register(Post) #add this to register the Post model
Run : C:\my_project_django\testdev>python manage.py runserver

Related Post