article

Friday, May 29, 2020

Django How to Implement CRUD (Create Read Update Delete) Using Ajax and Json


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 Table
CREATE 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);

});

Related Post