【Django】教程-11-ajax弹窗实现增删改查

【Django】教程-1-安装+创建项目+目录结构介绍
【Django】教程-2-前端-目录结构介绍
【Django】教程-3-数据库相关介绍
【Django】教程-4-一个增删改查的Demo
【Django】教程-5-ModelForm增删改查+规则校验【正则+钩子函数】
【Django】教程-6-搜索框-条件查询前后端
【Django】教程-7-分页,默认使用django的
【Django】教程-8-页面时间组件
【Django】教程-9-登录+退出
【Django】教程-10-ajax请求Demo,结合使用

17. ajax弹窗方式实现-增删改查

由下面几个模块组成 : model -> From -> urls -> views ->html

17.1 model

models.py

python 复制代码
from django.utils import timezone
from django.db import models


class Order(models.Model):
    """ 订单表"""
    num = models.CharField(verbose_name="订单号", max_length=64)
    goods_name = models.CharField(verbose_name="商品名称", max_length=64)
    price = models.IntegerField(verbose_name="价格")
    status_choices = (
        (1, "待支付"),
        (2, "已支付"),
    )
    status = models.SmallIntegerField(verbose_name="订单状态", choices=status_choices, default=1)
    seller = models.ForeignKey(verbose_name="客服", to="UserInfo", on_delete=models.CASCADE)
    
class UserInfo(models.Model):
    '''用户表'''
    name = models.CharField(verbose_name="姓名", max_length=32)
    password = models.CharField(verbose_name="密码", max_length=64)
    age = models.IntegerField(verbose_name="年龄")
    # create_time = models.DateTimeField(verbose_name="创建时间", default=timezone.now)
    create_time = models.DateField(verbose_name="创建时间", default=timezone.now)
    depart = models.ForeignKey(verbose_name="部门", to="Department", to_field="id", null=True, blank=True,
                               on_delete=models.SET_NULL)

    gender_choices = (
        (1, "男"),
        (2, "女"),
    )
    gender = models.SmallIntegerField(verbose_name="性别", choices=gender_choices, default=1)
    # 数据状态
    status_choices = (
        (1, "已删除"),
        (0, "可用"),
    )
    status = models.SmallIntegerField(verbose_name="数据状态", choices=status_choices, default=0)

    def __str__(self):
        return self.name

17.2 Form

forms.py

python 复制代码
from django import forms
from django.core.exceptions import ValidationError
from django.core.validators import RegexValidator

from . import models
from .models import Department, UserInfo, Admin, Order
from .util.md5 import md5


class BootstrapModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # 循环Modelform中所有字段,给每个字段插件设置
        for name, field in self.fields.items():
            if field.widget.attrs:
                field.widget.attrs["class"] = "form-control"
                field.widget.attrs["placeholder"] = field.label
            else:
                field.widget.attrs = {"class": "form-control", "placeholder": field.label}

    def as_div(self):
        """
        自定义表单渲染方法,将错误信息显示在字段下方并设置为红色
        """
        output = []
        for bound_field in self:
            label_html = f'<label for="{bound_field.id_for_label}">{bound_field.label}</label>'
            field_html = f'<div class="form-group">{label_html}{bound_field}</div>'
            if bound_field.errors:
                error_html = ''.join([f'<span class="text-danger">{error}</span>' for error in bound_field.errors])
                field_html += f'<div class="error-message">{error_html}</div>'
            output.append(field_html)
        return '\n'.join(output)

class OrderForm(BootstrapModelForm):
    class Meta:
        model = Order
        # fields = "__all__"
        exclude = ["num", "id"]

17.3 urls

urls.py

python 复制代码
from django.contrib import admin
from django.urls import path
from appTang.views import department_views, user_views, admin_views, account, order_view

# 映射关系,视图--->函数
urlpatterns = [
#     --------------------订单管理------------
    path('order/list', order_view.list),
    path('order/add', order_view.add),
    path('order/del', order_view.delete),
    path('order/detail', order_view.detail),
    path('order/edit', order_view.edit),

]

17.4 views

views.py

python 复制代码
import random
from datetime import datetime

from django.core.paginator import Paginator
from django.http import JsonResponse
from django.shortcuts import redirect, render
from django.views.decorators.csrf import csrf_exempt

from appTang.forms import OrderForm
from appTang.models import Order


def list(request):
    """用户展示"""

    # 搜索条件
    data_dict = {}
    query_name = request.GET.get("query_name", "")  # 第二个值是默认值, 也可以写if判断
    if query_name:
        data_dict["name__contains"] = query_name
    order_list = Order.objects.filter(**data_dict).order_by("-id")

    paginator = Paginator(order_list, 5)
    # 获取当前页码,默认为第 1 页
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    context = OrderForm()

    return render(request, 'order/order_list.html', {'page_obj': page_obj, 'context': context})


@csrf_exempt
def add(request):
    form = OrderForm(data=request.POST)
    if form.is_valid():
        form.instance.num = datetime.now().strftime('%Y%m%d%H%M%S') + str(random.randint(1000, 9999))
        form.save()
        return JsonResponse({"status": True})
    return JsonResponse({"status": False, "error": form.errors})


def delete(request):
    """删除订单"""
    uid = request.GET.get("uid")
    exists = Order.objects.filter(id=uid).exists()
    if not exists:
        return JsonResponse({"status": False, "error": "数据不存在,删除失败!"})
    Order.objects.filter(id=uid).delete()
    return JsonResponse({"status": True})


def detail(request):
    """编辑订单,回显"""
    uid = request.GET.get("uid")
    row_dict = Order.objects.filter(id=uid).values("goods_name", "status", "price", "seller").first()
    if not row_dict:
        return JsonResponse({"status": False, "error": "数据不存在,编辑失败!"})


    return JsonResponse({"status": True, "data": row_dict})

@csrf_exempt
def edit(request):
    """编辑订单"""
    uid = request.GET.get("uid")
    row_obj = Order.objects.filter(id=uid).first()
    if not row_obj:
        return JsonResponse({"status": False, "tips": "数据不存在!请刷新重试!"})
    form = OrderForm(data=request.POST, instance=row_obj)
    if form.is_valid():
        form.save()
        return JsonResponse({"status": True})

    return JsonResponse({"status": False, "error": form.errors})

17.5 html

order_list.html

html 复制代码
{% extends 'login/layout.html' %}
{% load static %}

{% block content %}
    <div class="container">
        <div style="margin-bottom: 10px">
            <input id="btnAdd" type="button" value="新建订单js" class="btn btn-success">

            <input type="button" value="新建订单2-css" class="btn btn-success" data-toggle="modal" data-target="#myModal">
        </div>
        <div class="panel panel-default">
            <div class="panel-heading"><span class="glyphicon glyphicon-th-list" aria-hidden="true"></span>订单列表
            </div>
            <table class="table table-bordered">
                <thead>
                <tr>
                    <th>#</th>
                    <th>订单号</th>
                    <th>商品名称</th>
                    <th>价格</th>
                    <th>状态</th>
                    <th>客服</th>
                    <th>操作</th>
                </tr>
                </thead>
                <tbody>
                {% for i in page_obj %}
                    <tr>
                        <td>{{ i.id }}</td>
                        <td>{{ i.num }}</td>
                        <td>{{ i.goods_name }}</td>
                        <td>{{ i.price }}</td>
                        <td>{{ i.get_status_display }}</td>
                        <td>{{ i.seller }}</td>
                        <td>
                            <input uid="{{ i.id }}" class="btn btn-primary btn-xs btn-edit" type="button" value="编辑">
                            <input uid="{{ i.id }}" class="btn btn-danger btn-xs btn-delete" type="button" value="删除">
                        </td>
                    </tr>
                {% endfor %}
                </tbody>
            </table>
        </div>

        <!-- 分页导航 -->
        <nav aria-label="分页">
            <ul class="pagination justify-content-center"
                style="display: flex; flex-wrap: nowrap; align-items: center;">
                <!-- 首页 -->
                {% if page_obj.has_previous %}
                    <li class="page-item">
                        <a class="page-link" href="?page=1">首页</a>
                    </li>
                {% else %}
                    <li class="page-item disabled">
                        <span class="page-link">首页</span>
                    </li>
                {% endif %}

                <!-- 上一页 -->
                {% if page_obj.has_previous %}
                    <li class="page-item">
                        <a class="page-link" href="?page={{ page_obj.previous_page_number }}">上一页</a>
                    </li>
                {% else %}
                    <li class="page-item disabled">
                        <span class="page-link">上一页</span>
                    </li>
                {% endif %}

                <!-- 下拉选择页码 -->
                <li class="page-item" style="margin: 0 5px;">
                    <select class="form-control" onchange="goToPage(this.value)">
                        {% for page_num in page_obj.paginator.page_range %}
                            <option value="{{ page_num }}" {% if page_num == page_obj.number %}selected{% endif %}>
                                第 {{ page_num }} 页
                            </option>
                        {% endfor %}
                    </select>
                </li>

                <!-- 显示当前页码和总页数 -->
                <li class="page-item disabled" aria-current="page" style="margin: 0 5px;">
                    <span class="page-link">共 {{ page_obj.paginator.num_pages }} 页</span>
                </li>

                <!-- 下一页 -->
                {% if page_obj.has_next %}
                    <li class="page-item">
                        <a class="page-link" href="?page={{ page_obj.next_page_number }}">下一页</a>
                    </li>
                {% else %}
                    <li class="page-item disabled">
                        <span class="page-link">下一页</span>
                    </li>
                {% endif %}

                <!-- 尾页 -->
                {% if page_obj.has_next %}
                    <li class="page-item">
                        <a class="page-link" href="?page={{ page_obj.paginator.num_pages }}">尾页</a>
                    </li>
                {% else %}
                    <li class="page-item disabled">
                        <span class="page-link">尾页</span>
                    </li>
                {% endif %}
            </ul>
        </nav>

    </div>


    <!-- 新建订单/ 编辑订单 对话框 -->
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span
                            aria-hidden="true">&times;</span></button>
                    <h4 class="modal-title" id="myModalLabel">新建订单</h4>
                </div>
                <div class="modal-body">
                    <form id="formAdd">
                        <div class="clearfix">
                            {% for i in context %}
                                <div class="col-xs-6">
                                    <div class="form-group" style="">
                                        <label>{{ i.label }}</label>
                                        {{ i }}
                                        <span class="error-msg" style="color: red"></span>
                                    </div>

                                </div>
                            {% endfor %}
                        </div>
                    </form>


                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
                    <button id="btnSave" type="button" class="btn btn-primary">保存</button>
                </div>
            </div>
        </div>
    </div>


    <!-- 删除 对话框 -->
    <div class="modal fade" id="delModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
        <div class="modal-dialog" role="document">
            <div class="alert alert-danger alert-dismissible fade in" role="alert">
                <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span
                        aria-hidden="true">×</span></button>
                <h4>是否确认删除?</h4>
                <p style="margin: 10px 10px;">删除后,所有关联都会被删除</p>
                <p style="text-align: right">
                    <button type="button" class="btn btn-danger" id="btnConfirmDel">确定</button>
                    <button type="button" class="btn btn-default" data-dismiss="modal">取消</button>
                </p>
            </div>
        </div>
    </div>

{% endblock %}
{% block js %}
    <script src=https://code.jquery.com/jquery-3.6.0.min.js></script>
    <script type="text/javascript">
        //声明 一个全部变量 delete_id
        var DELETE_ID;
        var EDIT_ID;
        $(function () {
            bindBtnAddEvent();
            bindBtnSaveEvent();
            bindBtnDelEvent();
            bindBtnConfirmDelEvent();
            bindBtnEditEvent();
        })

        function bindBtnEditEvent() {
            $(".btn-edit").click(function () {
                // 清空对话框中的数据
                $("#formAdd")[0].reset()
                var uid = $(this).attr("uid")
                EDIT_ID = uid

                // 从后端获取数据,并回显展示
                $.ajax({
                    url: "/order/detail",
                    type: "GET",
                    data: {
                        uid: uid
                    },
                    dataType: "JSON",
                    success: function (res) {
                        // console.log(res)
                        if (res.status) {
                            // 讲数据,进行赋值
                            $.each(res.data, function (name, value) {
                                // console.log(name,value)
                                $("#id_" + name).val(value);
                            })
                            // 设置编辑页
                            $("#myModalLabel").text("编辑")
                            // 点击编辑
                            $("#myModal").modal('show');

                        } else {
                            alert(res.error)
                        }
                    }
                })
            })
        }

        function bindBtnConfirmDelEvent() {
            $("#btnConfirmDel").click(function () {
                // console.log("点击了确定按钮")
                // 点击确认删除按钮,将全局变量中设置的那个ID,发送到后台
                $.ajax({
                    url: "/order/del",
                    type: "GET",
                    data: {
                        uid: DELETE_ID
                    },
                    dataType: "JSON",
                    success: function (res) {
                        if (res.status) {
                            // 隐藏弹窗
                            // $("#delModal").modal('hide');
                            // 页面刷新
                            location.reload();

                        } else {
                            // 删除失败
                            alert(res.error)
                        }
                    }
                })
            })
        }

        function bindBtnAddEvent() {
            $("#btnAdd").click(function () {
                // 将正在编辑的EDIT_ID置为空
                EDIT_ID = undefined;

                // 清空对话框中的数据
                $("#formAdd")[0].reset()
                $("#myModalLabel").text("新建")
                // 点击按钮显示对话框
                $("#myModal").modal('show');
            })
        }

        function bindBtnDelEvent() {
            $(".btn-delete").click(function () {
                // alert("点击了删除")
                // 弹出一个对话框
                $("#delModal").modal('show');
                // 获取当前uid 赋值 给全局变量
                // var uid = $(this).attr("uid")
                // console.log(uid)
                DELETE_ID = $(this).attr("uid")

            })

        }

        function bindBtnSaveEvent() {
            $("#btnSave").click(function () {
                // 清除错误信息
                $(".error-msg").empty()

                if (EDIT_ID) {
                    // 编辑
                    edit();
                } else {
                    // 添加
                    add();
                }


            })
        }

        function edit() {
            // 向后台发送请求
            $.ajax({
                url: "/order/edit" + "?uid=" + EDIT_ID, // /order/edit?uid=3
                type: "POST",
                data: $("#formAdd").serialize(),
                dataType: "JSON",
                success: function (res) {
                    if (res.status) {
                        alert("编辑保存成功!")
                        // 清空表单,$("#formAdd")jQuery对象->Dom对象$("#formAdd")[0]
                        $("#formAdd")[0].reset();
                        // 关闭对话框
                        $("#myModal").modal('hide');
                        // 页面刷新
                        location.reload()
                    } else {
                        if (res.tips) {
                            alert(res.tips)
                        } else {
                            $.each(res.error, function (name, errorList) {
                                $("#id_" + name).next().text(errorList[0]);
                            })
                        }

                    }
                }
            })
        }

        function add() {
            // 向后台发送请求
            $.ajax({
                url: "/order/add",
                type: "POST",
                data: $("#formAdd").serialize(),
                dataType: "JSON",
                success: function (res) {
                    if (res.status) {
                        alert("创建成功!")
                        // 清空表单,$("#formAdd")jQuery对象->Dom对象$("#formAdd")[0]
                        $("#formAdd")[0].reset();
                        // 关闭对话框
                        $("#myModal").modal('hide');
                        // 页面刷新
                        location.reload()
                    } else {
                        $.each(res.error, function (name, errorList) {
                            $("#id_" + name).next().text(errorList[0]);
                        })
                    }
                }
            })
        }
    </script>
{% endblock %}

17.6 目录结构

相关推荐
唐古乌梁海4 小时前
【Django】教程-15-注册页面
django
浪淘沙jkp5 小时前
智慧水务项目(八)基于Django 5.1 版本PyScada详细安装实战
后端·python·django·pyscada
咖啡调调。8 小时前
模板引擎语法-变量
django·sqlite
桃子不吃李子18 小时前
前端学习10—Ajax
前端·学习·ajax
quo-te19 小时前
AJAX简介
前端·ajax·okhttp
#岩王爷1 天前
Ajax------免刷新地前后端交互
前端·javascript·ajax·php
仰望星空的小随1 天前
django相关面试题
python·django·sqlite
唐古乌梁海1 天前
【Django】教程-14-验证码+登录页
django
MarkHD1 天前
第十二天 - Flask/Django基础 - REST API开发 - 练习:运维管理后台API
运维·django·flask