您现在的位置是:首页 > 文章详情

利用bootstrap模态框+ajax对数据进行增删改

日期:2021-05-07点击:489

接上篇:
1.数据库改动,添加外键,多对多
model.py

from django.db import models # Create your models here. GENDER = { ('male', '男'), ('female', '女'), } class User(models.Model): username=models.CharField(max_length=32,null=False) password=models.CharField(max_length=32,null=False) email = models.EmailField(null=True) name = models.CharField(max_length=20, null=True) tel = models.CharField(max_length=20, null=True) gender = models.CharField(max_length=20, choices=GENDER) birthday = models.DateTimeField(null=True) class Proxy(models.Model): ng_name=models.CharField(max_length=20) class Domain(models.Model): domain=models.CharField(max_length=125,null=False) src=models.CharField(max_length=125,null=False) User=models.ForeignKey(User,on_delete=models.CASCADE) m=models.ManyToManyField(Proxy) 

核心部分之view

from django.core.exceptions import ValidationError from django.db import IntegrityError from django.shortcuts import redirect, render, HttpResponse from cdnpanel.models import User, Domain, Proxy import json def index(request): if request.COOKIES.get("is_login"): username = request.COOKIES.get('username') data = Domain.objects.filter(User__username=username) engine = Proxy.objects.all() user = User.objects.all() return render(request, 'index.html', {'data': data, "engine": engine, "user": user}) else: return redirect('/login') def login(request): if request.method == "POST": ajax_rep = {"status": "err", "msg": None} user = request.POST.get('username') pwd = request.POST.get('password') if not User.objects.filter(username=user).exists(): ajax_rep['msg'] = "用户不存在" elif not User.objects.filter(username=user, password=pwd).exists(): ajax_rep['msg'] = "密码错误" else: ajax_rep['status'] = 'ok' rep = HttpResponse(json.dumps(ajax_rep)) rep.set_cookie("is_login", True) rep.set_cookie("username", user) return rep return HttpResponse(json.dumps(ajax_rep)) return render(request, "login.html") def register(request): if request.method == "POST": ajax_rsp = {"status": "ok", "msg": None} try: if request.is_ajax(): username = request.POST.get('username') password = request.POST.get('password') name = request.POST.get('name') email = request.POST.get('email') tel = request.POST.get('tel') gender = request.POST.get('gender') birthday = request.POST.get('birthday') if User.objects.filter(username=username).exists(): ajax_rsp["status"] = "err" ajax_rsp["msg"] = "用户已存在" else: User.objects.create( username=username, password=password, email=email, name=name, tel=tel, gender=gender, birthday=birthday, ) except IntegrityError: ajax_rsp["status"] = "err" ajax_rsp['msg'] = "性别为必选项" except ValidationError: ajax_rsp["status"] = "err" ajax_rsp['msg'] = "日期为必选项" return HttpResponse(json.dumps(ajax_rsp)) else: return render(request, "register.html") def add_domain(request): if request.is_ajax(): print(request.POST) ajax_rsp = {'status': "err", "msg": None, "yourself": "yes"} try: domain = request.POST.get("domain") src = request.POST.get("src") user = request.POST.get("username") if not user == request.COOKIES.get('username'): ajax_rsp["yourself"] = "no" user_id = User.objects.get(username=user).id ng_id = [] ng = request.POST.getlist('ng_name') for n in ng: nid = Proxy.objects.get(ng_name=n).id ng_id.append(nid) Domain.objects.create(domain=domain, src=src, User_id=user_id) obj = Domain.objects.get(domain=domain) obj.m.set(ng_id) ajax_rsp['data_id'] = obj.id ajax_rsp['status'] = 'ok' except Exception as e: print(e) ajax_rsp['msg'] = str(e) return HttpResponse(json.dumps(ajax_rsp)) return redirect('/index') def del_domain(request): if request.is_ajax(): ajax_rsp = {'status': "err", "msg": None} try: del_data_id=request.POST.get("del_data_id") print(del_data_id) Domain.objects.get(id=del_data_id).delete() ajax_rsp['status'] = "ok" except Exception as e: print(e) ajax_rsp['msg'] = str(e) return HttpResponse(json.dumps(ajax_rsp)) def update_domain(request): if request.is_ajax(): if request.method == "GET": ajax_rsp = {"status": "err"} try: data_id=request.GET.get("data_id") domain=Domain.objects.filter(id=data_id).first() ajax_rsp["domain"]=domain.domain ajax_rsp["src"]=domain.src ajax_rsp["user"]=User.objects.get(domain__domain=domain.domain,domain__id=data_id).username engine_list=[] for item in Proxy.objects.filter(domain__domain=domain.domain): engine_list.append(item.ng_name) ajax_rsp["engine"]=engine_list ajax_rsp["status"]='ok' print(ajax_rsp) except Exception as e: print(e) ajax_rsp['msg'] = str(e) return HttpResponse(json.dumps(ajax_rsp)) elif request.method == "POST": print(request.POST) ajax_rsp = {'status': "err", "msg": None, "yourself": "yes"} try: old_id = request.POST.get("data_id") domain = request.POST.get("domain") src = request.POST.get("src") user = request.POST.get("username") if not user == request.COOKIES.get('username'): ajax_rsp["yourself"] = "no" user_id = User.objects.get(username=user).id ng_id = [] ng = request.POST.getlist('ng_name') for n in ng: nid = Proxy.objects.get(ng_name=n).id ng_id.append(nid) Domain.objects.filter(id=old_id).update(domain=domain, src=src, User_id=user_id) obj = Domain.objects.get(domain=domain,src=src) obj.m.set(ng_id, clear=True) ajax_rsp['status'] = 'ok' except Exception as e: ajax_rsp['msg'] = str(e) return HttpResponse(json.dumps(ajax_rsp)) def test(request): print(Domain.objects.get(domain="2343165sada4864sdsa.tw")) return render(request, 'test.html') 

核心部分之index.html

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> {% load static %} <link rel="stylesheet" href="{% static 'plugin/bootstrap/css/bootstrap.min.css' %}"> <link href="//netdna.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet"> <style> .table{ width: 300px; } </style> <body> <p></p> <div> <button type="button" class="btn btn-success" data-toggle="modal" data-target="#addModal">添加</button> </div> <p></p> <div> <table class="table table-bordered"> <thead> <tr> <th>域名</th> <th>源</th> <th>操作</th> </tr> </thead> <tbody> {% for item in data %} <tr data_id="{{ item.id }}"> <td>{{ item.domain }}</td> <td>{{ item.src }}</td> <td> <a data-toggle="modal" data-target="#delModal" id="del_icon" class="fa fa-trash-o fa-lg"></a> <a data-toggle="modal" data-target="#editModal" class="fa fa-pencil fa-fw"></a> </td> </tr> {% endfor %} </tbody> {# 添加模态对话框#} <div class="modal fade" id="addModal" tabindex="-1" role="dialog" aria-labelledby="addModalLabel"> <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="addModalLabel">New message</h4> </div> <div class="modal-body"> <form action="add_domain" id="modal_form" method="post"> <div class="form-group"> <label for="inputEmail3" class="col-sm-2 control-label">域名:</label> <input type="text" name="domain" class="form-control" id="inputEmail3" placeholder="域名"> </div> <div class="form-group"> <label class="col-sm-2 control-label">源:</label> <input name="src" class="form-control" placeholder="1.1.1.1"> </div> <div class="form-group"> {% for ng in engine %} <input type="checkbox" name="ng_name" value="{{ ng.ng_name }}">{{ ng.ng_name }} {% endfor %} </div> <div class="form-group"> <select name="username" > {% for u in user %} <option value="{{ u.username }}">{{ u.username }}</option> {% endfor %} </select> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-submit add_submit">提交</button> </div> </div> </div> </div> </table> </div> {#删除模态框#} <!-- Modal --> <div class="modal fade " id="delModal" tabindex="-1" role="dialog" aria-labelledby="delModalLabel"> <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="delModalLabel" style="color: red" >危险!!</h4> </div> <div class="modal-body alert alert-danger" > 此操作不可以逆!是否删除? </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-danger del_submit">确认删除</button> </div> </div> </div> </div> {#编辑模态框#} <div class="modal fade" id="editModal" tabindex="-1" role="dialog" aria-labelledby="editModalLabel"> <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="editModalLabel">update</h4> </div> <div class="modal-body"> <form action="update_domain" id="modal_form" method="post"> <div class="form-group"> <label for="inputEmail3" class="col-sm-2 control-label">域名:</label> <input type="text" name="domain" class="form-control" id="inputEmail3" > </div> <div class="form-group"> <label class="col-sm-2 control-label">源:</label> <input name="src" class="form-control" > </div> <div class="form-group"> {% for ng in engine %} <input type="checkbox" name="ng_name" value="{{ ng.ng_name }}">{{ ng.ng_name }} {% endfor %} </div> <div class="form-group"> <select name="username" > {% for u in user %} <option value="{{ u.username }}">{{ u.username }}</option> {% endfor %} </select> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Close</button> <button type="button" class="btn btn-submit edit_submit">提交</button> </div> </div> </div> </div> </table> </div> </body> <script src="/static/js/jquery-3.5.1.min.js"> </script> <script src="{% static 'plugin/bootstrap/js/bootstrap.min.js' %}"> </script> <script> $(".add_submit").click(function (){ var data=$("#addModal form").serialize() console.log(data) $.ajax({ data:data, dataType:"json", "type":"POST", "url":'/add_domain', "success":function (arg) { {#若添加的是自己的数据则在前端显示#} if(arg.yourself=="yes") { console.log(arg.msg) postdata = "{\"" + data.replace(RegExp("=", "g"), "\":\"").replace(RegExp("&", 'g'), "\",\"") + "\"}"; postdata = JSON.parse(postdata) console.log(postdata.domain) data_id=arg.data_id var tr_ele = $("<tr></tr>") tr_ele.attr("data_id",data_id) var dtd_ele = $("<td></td>").text(postdata.domain) var std_ele = $("<td></td>").text(postdata.src) var action_ele = '<td><a data-toggle="modal" data-target="#delModal" id="del_icon" class="fa fa-trash-o fa-lg"></a> <a data-toggle="modal" data-target="#editModal" class="fa fa-pencil fa-fw"></a></td>' tr_ele.append(dtd_ele) tr_ele.append(std_ele) tr_ele.append(action_ele) $("tbody").append(tr_ele) } $('#addModal').modal('hide') document.getElementById("modal_form").reset() } }) }) {# 删除函数 #} var data_id; {# 定义一个全局变量传递修改数据的id值 #} {#$(".fa-trash-o").click(function (){#} $(document).on("click",".fa-trash-o",function (){ data_id=$(this).parent().parent().attr("data_id") $(this).parent().parent().attr("id","del_targer"){# 因为没法通过data_id删除元素,给点击的tr标签加了个唯一id标识 #} $(".del_submit").click(function(){ var postdata={}; postdata['del_data_id']=data_id console.log(data_id) $.ajax({ data:postdata, dataType:"json", "type": "POST", "url":'/del_domain', "success":function (arg){ if(arg.status=="ok"){ $("#del_targer").remove() $('#delModal').modal('hide') } } }) }) }) {# 编辑函数 #} {# $(".fa-pencil").click(function (){#} $(document).on("click",".fa-pencil",function (){ data_id=data_id=$(this).parent().parent().attr("data_id") {# 直接从前端获取数据太麻烦,这里用ajax获取数据赋值#} $(this).parent().parent().attr("id","edit_targer") $.ajax({ type:"GET", data:{"data_id":data_id}, "url":'/update_domain', dataType:"json", "success":function (arg){ if(arg.status=="ok"){ $("#editModal input[name='domain']").val(arg.domain) $("#editModal input[name='src']").val(arg.src) $("#editModal option[value="+arg.user+"]").prop("selected",true) for (item in arg.engine) { ng_name=arg.engine[item] $("#editModal input[value="+ng_name+"]").prop("checked",true) } } } }) $(".edit_submit").click(function (){ var data=$("#editModal form").serialize() postdata = "{\"" + data.replace(RegExp("=", "g"), "\":\"").replace(RegExp("&", 'g'), "\",\"") + "\"}"; postdata = JSON.parse(postdata) postdata["data_id"]=data_id $.ajax({ data:postdata, dataType:"json", "type":"POST", "url":'/update_domain', "success":function (arg) { {#若修改的是自己的数据则在前端显示#} if (arg.status == 'ok') { if (arg.yourself == "yes") { var tr_ele = $("#edit_targer") tr_ele.empty() var dtd_ele = $("<td></td>").text(postdata.domain) var std_ele = $("<td></td>").text(postdata.src) var action_ele = '<td><a data-toggle="modal" data-target="#delModal" id="del_icon" class="fa fa-trash-o fa-lg"></a> <a data-toggle="modal" data-target="#editModal" class="fa fa-pencil fa-fw"></a></td>' tr_ele.append(dtd_ele) tr_ele.append(std_ele) tr_ele.append(action_ele) }else { var tr_ele = $("#edit_targer") tr_ele.empty() } $('#editModal').modal('hide') $("#edit_targer").attr("id","") } } }) }) }) $(".btn-default").click(function (){ document.getElementById("modal_form").reset() $(":checked").prop("checked",false) $(":selected").prop("selected",false) $("#del_targer").attr("id","") $("#edit_targer").attr("id","") }) </script> </html>

url部分

urlpatterns = [ path('admin/', admin.site.urls), re_path('index', views.index), re_path('register', views.register), re_path('login', views.login), re_path('add_domain', views.add_domain), re_path('del_domain', views.del_domain), re_path('update_domain', views.update_domain), re_path('test', views.test), ]

思路历程简介:

1.登陆
上篇的登陆没有设置cookie,所以每次都要重复登陆,操作其实很简单,当用户名和密码匹配成功了,在cookie中设置自定义字段is_login=true,然后在index函数中取得该值并判断,代码部分如下

def index(request): if request.COOKIES.get("is_login"): username = request.COOKIES.get('username') data = Domain.objects.filter(User__username=username) engine = Proxy.objects.all() user = User.objects.all() return render(request, 'index.html', {'data': data, "engine": engine, "user": user}) else: return redirect('/login') def login(request): if request.method == "POST": ajax_rep = {"status": "err", "msg": None} user = request.POST.get('username') pwd = request.POST.get('password') if not User.objects.filter(username=user).exists(): ajax_rep['msg'] = "用户不存在" elif not User.objects.filter(username=user, password=pwd).exists(): ajax_rep['msg'] = "密码错误" else: ajax_rep['status'] = 'ok' rep = HttpResponse(json.dumps(ajax_rep)) rep.set_cookie("is_login", True) rep.set_cookie("username", user) return rep return HttpResponse(json.dumps(ajax_rep)) return render(request, "login.html")

2.添加数据
添加数据流程主要是:获取数据-->处理数据-->取得返回结果后展示

获取数据前还要先做填写数据的模态框,这里主要有个问题,因为涉及外键和多对多,所以要先有这些数据可以选,也就是模板里面必须传入外键表的值和多对多的值,我这里是
render(request, 'index.html', {'data': data, "engine": engine, "user": user})
然后用select元素作为多对多的选择项,checkbox为User的单选

<1>获取数据
因为填数据用的是form表单,所以这里获取数据很简单用serialize()函数
var data=$("#addModal form").serialize()
<2>处理数据
利用ajax传送,view函数处理即可
<3>数据显示
这里有个问题,serialize()函数处理出来的数据不是字典形式,而是类似get请求的形式:”username=linzb&password=123456“,所以要对其进行分割取值,才能对元素进行赋值
(这里我还多赋值一个yourself字段,判断是否为当前登录用户,是才显示)

3.删除
要删除,首先服务端要知道数据是什么,其次,服务端删除成功后,前端要删除对应元素,所以删除部分可以归结为一个问题:如何对原来的数据进行定位?

这里我利用了一个全局变量data_id(生成数据的时候在tr上赋值数据id),在点击删除按钮的时候,通过this关键字找到这个数据id并传递给data_id,并在id打了个del_tager标记,于是问题解决: <1>data_id通过ajax传递给服务端,服务端找到对应数据del <2>返回结果后,前端通过#del_tager找到标签并删除 (这里也许有人会问为什么不直接通过data_id,而要多此一举,这是因为我测试多次这方法行不通,才选择用del_targer)

4.编辑
编辑比添加多了两步
<1>打开模态框的时候要为模态框赋值(这里我采用ajax从服务端取值,这方法不推荐,从前端取值对服务端更友善)
<2>成功执行后要在前端进行修改而不是添加

debug:

1.django 设置cookie需要用变量过渡,直接引用会报错 正确: rep=HttpResponse(json.dumps(ajax_rep)) rep.set_cookie("is_login",True) return rep 错误: return HttpResponse(json.dumps(ajax_rep)).set_cookie("is_login",True) 2. 给标签加 data-toggle="modal" data-target="#exampleModal"属性,点击没反应 测试发现是忘了加载bootstrap.min.js 3.ValueError: too many values to unpack (expected 2) 排查发现:Proxy.objects.get(ng_name=n).id写成了: Proxy.objects.get(n).id 少了字段名 4.添加时的元素位置和插入问题 想要的代码形式: <tbody> <tr> <td>已存在的数据</tr> </tr> <tr> <td>新增加的数据<td> </tr> </tbody> var tr_ele =$("<tr></tr>") var dtd_ele =$("<td></td>").text(新增加的数据) tr_ele.append(std_ele) $("tbody").append(tr_ele) 之前用:tr_ele.text(dtd_ele)和$("tbody tr").append(tr_ele)一直搞不定 错误原因在于没有意识到append是在内部添加,before()和after() 是在外部 5.Bootstrap 模态框使用 <1>以id为标识,内容标签包裹头部,body和尾部 <div class="modal fade" id="delModal" tabindex="-1" role="dialog" aria-labelledby="delModalLabel"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> </div> <div class="modal-body " > </div> <div class="modal-footer"> </div> </div> </div> </div> <2>用data-target指向id引用 <a data-toggle="modal" data-target="#delModal" id="del_icon" class="fa fa-trash-o fa-lg"></a> 6.jquery attr()和prop()区别 <1>取自定义属性用attr() (下面摘抄自:https://www.jb51.net/article/140974.htm) 1.添加属性名称该属性就会生效应该使用prop(); 2.是有true,false两个属性使用prop();(如'checked','selected','disabled'等) 3.其他则使用attr(); 7.模态框退出,清空表单输入值的方法(利用form表单的reset) 由于jquery没有reset()方法,可以给表单赋予id,然后reset() document.getElementById("modal_form").reset() 选择按钮则需要去掉对应属性 $(":checked").prop("checked",false) $(":selected").prop("selected",false) 8.编辑模态框完成后发现添加数据时报错 后面print (POST数据)发现数据取了多行 原因:取数据时没有区分form表单 原来:var data=$("form").serialize() 修改:var data=$("#addModal form").serialize() 9.多对多表更新,加上clear=True就可以 obj.m.set(ng_id,clear=True) 意为先清空后添加 10.做删除的时候利用tr传递data_id,添加的时候也必须加上 11.事件委托on语法: $(document).on("click",".fa-trash-o",function (){}) on("事件","选择标签",函数(){}) 删除时的思路:点击模态按钮时必须获取当前的值,用全局变量传递 要删除整行,于是放在tr标签上 12.如果发现清空数据有问题用(找到对应位置即可,51编辑器不好用,懒得重复改): document.getElementById("modal_form").reset() $(":checked").prop("checked",false) $(":selected").prop("selected",false) $("#del_targer").attr("id","") $("#edit_targer").attr("id","")
原文链接:https://blog.51cto.com/linzb/2759206
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章