Django How to Implement CRUD (Create Read Update Delete) Using Ajax and Json
CRUD, it stand for Create Read Update Delete.
Models.py
#models.py
from django.db import models
class Product(models.Model):
FILLOW = 1
FOOD = 2
TOYS = 3
PRODUCT_TYPES = (
(FILLOW, 'Pillow'),
(FOOD, 'Food'),
(TOYS, 'Toys'),
)
name = models.CharField(max_length=50)
dateadded = models.DateField(blank=True, null=True)
productcode = models.CharField(max_length=30, blank=True)
price = models.DecimalField(max_digits=5, decimal_places=2)
quantity = models.IntegerField(blank=True, null=True)
category_type = models.PositiveSmallIntegerField(choices=PRODUCT_TYPES, blank=True, null=True)
class Meta:
db_table = "myapp_product"
Database TableCREATE TABLE myapp_product (
id INTEGER PRIMARY KEY,
name STRING (200),
productcode STRING (150),
price INTEGER,
quantity INTEGER,
category_type STRING (50),
dateadded DATE
);
Views.py
#views.py
from django.shortcuts import render, redirect, get_object_or_404
from myapp.models import Product
from myapp.forms import ProductForm
from django.http import JsonResponse
from django.template.loader import render_to_string
def index(request):
return render(request, 'index.html')
def product_list(request):
products = Product.objects.all()
return render(request, 'product_list.html', {'products': products})
def save_product_form(request, form, template_name):
data = dict()
if request.method == 'POST':
if form.is_valid():
form.save()
data['form_is_valid'] = True
products = Product.objects.all()
data['html_product_list'] = render_to_string('includes/partial_product_list.html', {
'products': products
})
else:
data['form_is_valid'] = False
context = {'form': form}
data['html_form'] = render_to_string(template_name, context, request=request)
return JsonResponse(data)
def product_create(request):
if request.method == 'POST':
form = ProductForm(request.POST)
else:
form = ProductForm()
return save_product_form(request, form, 'includes/partial_product_create.html')
def product_update(request, pk):
product = get_object_or_404(Product, pk=pk)
if request.method == 'POST':
form = ProductForm(request.POST, instance=product)
else:
form = ProductForm(instance=product)
return save_product_form(request, form, 'includes/partial_product_update.html')
def product_delete(request, pk):
product = get_object_or_404(Product, pk=pk)
data = dict()
if request.method == 'POST':
product.delete()
data['form_is_valid'] = True
products = Product.objects.all()
data['html_product_list'] = render_to_string('includes/partial_product_list.html', {
'products': products
})
else:
context = {'product': product}
data['html_form'] = render_to_string('includes/partial_product_delete.html', context, request=request)
return JsonResponse(data)
forms.py
#forms.py
from django import forms
from myapp.models import Product
class ProductForm(forms.ModelForm):
class Meta:
model = Product
fields = ('name', 'dateadded', 'productcode', 'price', 'quantity', 'category_type', )
urls.py
#urls.py
from django.contrib import admin
from django.urls import path
from myapp import views
from django.conf.urls import url
urlpatterns = [
path('admin/', admin.site.urls),
path('',views.index),
url(r'^products/$', views.product_list, name='product_list'),
url(r'^create/$', views.product_create, name='product_create'),
url(r'^products/(?P\d+)/update/$', views.product_update, name='product_update'),
url(r'^products/(?P\d+)/delete/$', views.product_delete, name='product_delete'),
]
settings.py pip install django-widget-tweaks
#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', #pip install django-widget-tweaks
]
//templates/index.html
{% extends 'base.html' %}
{% block content %}
<h1 class="page-header">Django How to Implement CRUD (Create Read Update Delete) Using Ajax and Json</h1>
<p class="lead">See the example clicking in the Product menu.</p>
<p class="lead"><a href="/products">Product List</a>.</p>
{% endblock %}
//templates/base.html
<!DOCTYPE html>
<html lang="en">
<head>
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'css/bootstrap.css' %}"/>
<meta charset="UTF-8" name="viewport" content="width=device-width, initial-scale=1"/>
<title>{% block title %}Django How to Implement CRUD (Create Read Update Delete) Using Ajax and Json{% endblock %}</title>
<link href="{% static 'css/bootstrap.min.css' %}" rel="stylesheet">
</head>
<body>
<nav class="navbar navbar-default">
<div class="container-fluid">
<a class="navbar-brand">Cairocoders</a>
</div>
</nav>
<div class="container">
<div class="col-md-12 well">
<h3 class="text-primary">Django How to Implement CRUD (Create Read Update Delete) Using Ajax and Json</h3>
<hr style="border-top:1px dotted #ccc;"/>
{% block content %}
{% endblock %}
</div>
</div>
<script src="{% static 'js/jquery-3.1.1.min.js' %}"></script>
<script src="{% static 'js/bootstrap.min.js' %}"></script>
{% block javascript %} {% endblock %}
</body>
</html>
//templates/product_list.html
{% extends 'base.html' %}
{% load static %}
{% block javascript %}
<script src="{% static 'js/script.js' %}"></script>
{% endblock %}
{% block content %}
<h1 class="page-header">Products</h1>
<p>
<button type="button" class="btn btn-primary js-create-product" data-url="{% url 'product_create' %}">
<span class="glyphicon glyphicon-plus"></span>
New Product
</button>
</p>
<table class="table" id="product-table">
<thead>
<tr>
<th>#</th>
<th>Name</th>
<th>Date Added</th>
<th>Category</th>
<th>Product Code</th>
<th>Quantiry</th>
<th>Price</th>
<th></th>
</tr>
</thead>
<tbody>
{% include 'includes/partial_product_list.html' %}
</tbody>
</table>
<div class="modal fade" id="modal-product">
<div class="modal-dialog">
<div class="modal-content">
</div>
</div>
</div>
{% endblock %}
//templates/includes/partial_product_create.html
<form method="post" action="{% url 'product_create' %}" class="js-product-create-form">
{% csrf_token %}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">Create a new product</h4>
</div>
<div class="modal-body">
{% include 'includes/partial_product_form.html' %}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Create product</button>
</div>
</form>
//templates/includes/partial_product_delete.html
<form method="post" action="{% url 'product_delete' product.id %}" class="js-product-delete-form">
{% csrf_token %}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">Confirm product deletion</h4>
</div>
<div class="modal-body">
<p class="lead">Are you sure you want to delete the product <strong>{{ product.name }}</strong>?</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-danger">Delete product</button>
</div>
</form>
//templates/includes/partial_product_form.html
{% load widget_tweaks %}
{% for field in form %}
<div class="form-group{% if field.errors %} has-error{% endif %}">
<label for="{{ field.id_for_label }}">{{ field.label }}</label>
{% render_field field class="form-control" %}
{% for error in field.errors %}
<p class="help-block">{{ error }}</p>
{% endfor %}
</div>
{% endfor %}
//templates/includes/partial_product_list.html
{% for product in products %}
<tr>
<td>{{ product.id }}</td>
<td>{{ product.name }}</td>
<td>{{ product.dateadded }}</td>
<td>{{ product.get_category_type_display }}</td>
<td>{{ product.productcode }}</td>
<td>{{ product.quantity }}</td>
<td>{{ product.price }}</td>
<td style="width: 150px">
<button type="button"
class="btn btn-warning btn-sm js-update-product"
data-url="{% url 'product_update' product.id %}">
<span class="glyphicon glyphicon-pencil"></span> Edit
</button>
<button type="button"
class="btn btn-danger btn-sm js-delete-product"
data-url="{% url 'product_delete' product.id %}">
<span class="glyphicon glyphicon-trash"></span> Delete
</button>
</td>
</tr>
{% empty %}
<tr>
<td colspan="8" class="text-center bg-warning">No product</td>
</tr>
{% endfor %}
//templates/includes/partial_product_update
<form method="post" action="{% url 'product_update' form.instance.pk %}" class="js-product-update-form">
{% csrf_token %}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
<h4 class="modal-title">Update product</h4>
</div>
<div class="modal-body">
{% include 'includes/partial_product_form.html' %}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Update product</button>
</div>
</form>
//static/js/script.js
$(document).ready(function(){
var loadForm = function () {
var btn = $(this);
$.ajax({
url: btn.attr("data-url"),
type: 'get',
dataType: 'json',
beforeSend: function () {
$("#modal-product .modal-content").html("");
$("#modal-product").modal("show");
},
success: function (data) {
$("#modal-product .modal-content").html(data.html_form);
}
});
};
var saveForm = function () {
var form = $(this);
$.ajax({
url: form.attr("action"),
data: form.serialize(),
type: form.attr("method"),
dataType: 'json',
success: function (data) {
if (data.form_is_valid) {
$("#product-table tbody").html(data.html_product_list);
$("#modal-product").modal("hide");
}
else {
$("#modal-product .modal-content").html(data.html_form);
}
}
});
return false;
};
/* Binding */
$(".js-create-product").click(loadForm);
$("#modal-product").on("submit", ".js-product-create-form", saveForm);
// Update product
$("#product-table").on("click", ".js-update-product", loadForm);
$("#modal-product").on("submit", ".js-product-update-form", saveForm);
// Delete product
$("#product-table").on("click", ".js-delete-product", loadForm);
$("#modal-product").on("submit", ".js-product-delete-form", saveForm);
});
