【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">×</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 目录结构
