Django 之 ORM 一对多、多对多 及 ajax 操作
一对多
数据库中一对多关系是最普通的一种关系。在这种关系中,A 表中的一行可以匹配 B 表中的多行,但是 B 表中的一行只能匹配 A 表中的一行。
如:部门表UserGroup 和 员工表Userinfo 之间具有一对多关系,一个部门可以有很多员工,一个员工仅属于一个部门。(这里仅举例便于理解,实际情况可能不是这样)
创建一对多关系表需要用到外键约束:ForeignKey("PrimaryTable",to_filed='xxx')
from django.db import models # Create your models here. class UserGroup(model s.Model): uid = models.AutoField(primary_key=True) #自定义自增列,必须声明primary_key=True caption = models.CharField(max_length=32,unique=True) class UserInfo(models.Model): username = models.CharField(max_length=32,blank=True,verbose_name='用户名') password = models.CharField(max_length=60, help_text='pwd') email = models.CharField(max_length=60) user_group = models.ForeignKey("UserGroup",to_field='uid',default=1) # default=1 表示默认属于哪个部门,django在数据库中将user_group存取字段为user_group_id,实际上user_group为UserGroup的对象封装了(uid,caption,ctime,uptime)
from app01 import models def orm(request): models.UserInfo.objects.create( username='root1', password='123', email="xxx.@qq.com", user_group = models.UserGroup.objects.filter(id=1).first() # 或 user_group_id = 1 (推荐) ) user_list = Userinfo.objects.all() for row in user_list: print(row.user_group) #这里 user_group代指 UserGroup 对象 print(row.user_group.id) # 等同于 print(row.user_group_uid) print(row.user_group.caption)
示例:用户管理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.conf.urls import url,include from django.contrib import admin from app01 import views urlpatterns = [ url(r'^login/', views.login), url(r'^index/', views.index), url(r'^user_info/', views.user_info), url(r'^userdetail-(?P<nid>\d+)/', views.user_detail), url(r'^userdel-(?P<nid>\d+)/', views.user_del), url(r'^useredit-(?P<nid>\d+)/', views.user_edit), ]
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
from django.shortcuts import render,HttpResponse,redirect def login(request): models.UserGroup.objects.create(caption='DBA') if request.method == "GET": return render(request, 'login.html') elif request.method == "POST": # 数据库中执行 select * from user where usernam='x' and password='x' u = request.POST.get('user') p = request.POST.get('pwd') # count = models.UserInfo.objects.filter(username=u, password=p).count() obj = models.UserInfo.objects.filter(username=u, password=p).first() if obj: return redirect('/cmdb/index/') else: return render(request, 'login.html') else: # PUT,DELETE,HEAD,OPTION... return redirect('/index/') def index(request): return render(request, 'index.html') def user_info(request): if request.method == "GET": user_list = models.UserInfo.objects.all() # print(user_list.query) group_list = models.UserGroup.objects.all() return render(request, 'user_info.html', {'user_list': user_list, "group_list": group_list}) elif request.method == 'POST': u = request.POST.get('user') p = request.POST.get('pwd') models.UserInfo.objects.create(username=u,password=p) return redirect('/cmdb/user_info/') def user_detail(request, nid): obj = models.UserInfo.objects.filter(id=nid).first() # models.UserInfo.objects.get(id=nid) # 取单条数据,但如果不存在则报错 return render(request, 'user_detail.html', {'obj': obj}) def user_del(request, nid): models.UserInfo.objects.filter(id=nid).delete() return redirect('/cmdb/user_info/') def user_edit(request, nid): if request.method == "GET": obj = models.UserInfo.objects.filter(id=nid).first() return render(request, 'user_edit.html',{'obj': obj}) elif request.method == "POST": nid = request.POST.get('id') u = request.POST.get('username') p = request.POST.get('password') models.UserInfo.objects.filter(id=nid).update(username=u,password=p) return redirect('/cmdb/user_info/')
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> body{ margin: 0; } .menu{ display: block; padding: 5px; } </style> </head> <body> <div style="height: 48px;background-color: black;color: white"> Deployment </div> <div> <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: brown;"> <a class="menu" href="/cmdb/user_info/">用户管理</a> <a class="menu" href="/cmdb/user_group/">用户组管理</a> </div> <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto"> </div> </div> </body> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> body{ margin: 0; } .menu{ display: block; padding: 5px; } </style> </head> <body> <div style="height: 48px;background-color: black;color: white"> Deployment </div> <div> <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: brown;"> <a class="menu" href="/cmdb/user_info/">用户管理</a> <a class="menu" href="/cmdb/user_group/">用户组管理</a> </div> <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto"> <h3>添加用户</h3> <form method="POST" action="/cmdb/user_info/"> <input type="text" name="user" /> <input type="text" name="pwd" /> <select name="group_id"> {% for item in group_list %} <option value="{{ item.uid }}">{{ item.caption }}</option> {% endfor %} </select> <input type="submit" value="添加"/> </form> <h3>用户列表</h3> <ul> {% for row in user_list %} <li> <a href="/cmdb/userdetail-{{ row.id }}/">{{ row.username }}</a> <span> {{ row.user_group.caption }} </span> <a href="/cmdb/userdel-{{ row.id }}/">删除</a> | <a href="/cmdb/useredit-{{ row.id }}/">编辑</a> </li> {% endfor %} </ul> </div> </div> </body> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> body{ margin: 0; } .menu{ display: block; padding: 5px; } </style> </head> <body> <div style="height: 48px;background-color: black;color: white"> Deployment </div> <div> <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: brown;"> <a class="menu" href="/cmdb/user_info/">用户管理</a> <a class="menu" href="/cmdb/user_group/">用户组管理</a> </div> <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto"> <h1>用户详细信息</h1> <h5>{{ obj.id }}</h5> <h5>{{ obj.name }}</h5> <h5>{{ obj.password }}</h5> </div> </div> </body> </html>
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> body{ margin: 0; } .menu{ display: block; padding: 5px; } </style> </head> <body> <div style="height: 48px;background-color: black;color: white"> Deployment </div> <div> <div style="position: absolute;top:48px;bottom: 0;left: 0;width: 200px;background-color: brown;"> <a class="menu" href="/cmdb/user_info/">用户管理</a> <a class="menu" href="/cmdb/user_group/">用户组管理</a> </div> <div style="position:absolute;top:48px;left: 210px;bottom: 0;right: 0;overflow: auto"> <h1>编辑用户</h1> <form method="post" action="/cmdb/useredit-{{ obj.id }}/"> <input style="display: none" type="text" name="id" value="{{ obj.id }}" /> <input type="text" name="username" value="{{ obj.username }}" /> <input type="text" name="password" value="{{ obj.password }}"/> <input type="submit" value="提交" /> </form> </div> </div> </body> </html>
一对多表 获取数据的三种方式
- models.表类名.objects.all() # QuerySet类型
- models.表类名.objects.all().values('f1','f2') # 取固定列的值,此时 QuerySet内部元素变成字典
- models.表类名.objects.all().values_list('f1','f2') # # 取固定列的值, 此时 QuerySet 内部元素变成元组
示例:业务线|主机列表
#=== models.py === from django.db import models class Foo(models.Model): name = models.CharField(max_length=1) class Business(models.Model): # id caption = models.CharField(max_length=32) code = models.CharField(max_length=32,null=True,default="SA") fk = models.ForeignKey('Foo') class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32,db_index=True) ip = models.GenericIPAddressField(protocol="ipv4",db_index=True) port = models.IntegerField() b = models.ForeignKey(to="Business", to_field='id')
#=== views.py === from django.shortcuts import render,HttpResponse,redirect from app01 import models def business(request): # 获取数据的三种方式 v1 = models.Business.objects.all() # QuerySet类型 <QuerySet [<Business: Business object>,<Business: Business object>,<Business: Business object>]> v2 = models.Business.objects.all().values('id','caption') # 取固定列的值,此时 QuerySet内部元素变成字典 [{'id':1,'caption': '运维部'},...] v3 = models.Business.objects.all().values_list('id','caption') # 取固定列的值, 此时 QuerySet 内部元素变成元组 [(1,运维部),(2,开发部)] return render(request, 'business.html', {'v1': v1,'v2': v2, 'v3': v3}) def host(request): v1 = models.Host.objects.filter(nid__gt=0) for row in v1: print(row.nid,row.hostname,row.ip,row.port,row.b_id,row.b.caption,row.b.code,row.b.id,sep='\t') print(row.b.fk.name) # 使用"."进行跨表操作 return HttpResponse("Host") v2 = models.Host.objects.filter(nid__gt=0).values('nid','hostname','b_id','b__caption') # 传参时只能用"__"跨表操作 print(v2) for row in v2: print(row['nid'],row['hostname'],row['b_id'],row['b__caption']) v3 = models.Host.objects.filter(nid__gt=0).values_list('nid','hostname','b_id','b__caption') print(v3) for row in v3: print(row[0],row[1],row[2],row[3]) return render(request, 'host.html', {'v1': v1,'v2': v2,'v3': v3})
=== business.html ===
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>业务线列表(对象)</h1> <ul> {% for row in v1 %} <li>{{ row.id }} - {{ row.caption }} - {{ row.code }}</li> {% endfor %} </ul> <h1>业务线列表(字典)</h1> <ul> {% for row in v2 %} <li>{{ row.id }} - {{ row.caption }}</li> {% endfor %} </ul> <h1>业务线列表(元组)</h1> <ul> {% for row in v3 %} <li>{{ row.0 }} - {{ row.1 }}</li> {% endfor %} </ul> </body> </html>
=== host.html ===
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h1>主机列表(对象)</h1> <table border="1"> <thead> <tr> <th>序号</th> <th>主机名</th> <th>IP</th> <th>端口</th> <th>业务线名称</th> <th>操作</th> </tr> </thead> <tbody> {% for row in v1 %} <tr hid="{{ row.nid }}" bid="{{ row.b_id }}"> <td>{{ forloop.counter }}</td> <!-- 计数器 counter,counter0,revcounter,revcounter0,first,last, parentcounter --> <td>{{ row.hostname }}</td> <td>{{ row.ip }}</td> <td>{{ row.port }}</td> <td>{{ row.b.caption }}</td> </tr> {% endfor %} </tbody> </table> <h1>主机列表(字典)</h1> <table border="1"> <thead> <tr> <th>主机名</th> <th>业务线名称</th> </tr> </thead> <tbody> {% for row in v2 %} <tr hid="{{ row.nid }}" bid="{{ row.b_id }}"> <td>{{ row.hostname }}</td> <td>{{ row.b__caption }}</td> </tr> {% endfor %} </tbody> </table> <h1>主机列表(元组)</h1> <table border="1"> <thead> <tr> <th>主机名</th> <th>业务线名称</th> </tr> </thead> <tbody> {% for row in v3 %} <tr hid="{{ row.0 }}" bid="{{ row.2 }}"> <td>{{ row.1 }}</td> <td>{{ row.3 }}</td> </tr> {% endfor %} </tbody> </table> </body> </html>
Ajax 提交数据
Ajax : Asynchronous JavaScript and XML,意思就是用JavaScript执行异步网络请求。
基于action的 Form表单提交基本流程: 提交 > url 路由 > 函数或类中的方法 进行逻辑处理 > 返回字符串(本质)> 用户
HttpResponse('xxx') # 返回字符串
render(request,'index.html') # open 函数打开html文件,进行渲染得到字符串
redirect('/index/') # 当接受到redirect时,自动发起另外一个请求
基于action的 Form表单,一旦用户点击“Submit”按钮,表单开始提交,浏览器就会刷新页面。
如果要让用户留在当前页面中,同时发出新的HTTP请求,就必须用JavaScript发送这个新请求,接收到数据后,再用JavaScript更新页面。注意:AJAX请求是异步执行的,要通过回调函数获得响应。
Ajax提交数据基本流程:提交 > url 路由 > 函数或类中的方法 进行逻辑处理 > 返回字符串 > 执行回调函数 > 用户
$.ajax({ url: '/index/', data: {'k1': 'v1', 'k2': [1,2,3,4], 'k3': JSON.stringfy({'k1': 'v'}))}, # 或 $(form对象).serilize() type: 'POST', dataType: 'JSON': traditional: true, success:function(d){ location.reload() # 刷新 location.href = "http://xxx" # 跳转 } })
变种: 内部都调用 $.ajax
$.get(url="xxx",data={},success="")
$.getJson
$.post
示例:添加 | 编辑主机
#=== views.py === from django.shortcuts import render,HttpResponse,redirect from app01 import models import json # 基于action提交Form表单数据的处理 def host(request): if request.method == "GET": v1 = models.Host.objects.filter(nid__gt=0) v2 = models.Host.objects.filter(nid__gt=0).values('nid','hostname','b_id','b__caption') v3 = models.Host.objects.filter(nid__gt=0).values_list('nid','hostname','b_id','b__caption') b_list = models.Business.objects.all() return render(request, 'host.html', {'v1': v1,'v2': v2,'v3': v3,'b_list':b_list}) elif request.method == "POST": h = request.POST.get('hostname') i = request.POST.get('ip') p = request.POST.get('port') b = request.POST.get('b_id') models.Host.objects.create(hostname=h,ip=i,port=p,b_id=b) # models.Host.objects.create(hostname=h,ip=i,port=p,b=models.Business.objects.get(id=b)) return redirect('/host') # return render(request,'host.html') 注意不能这样写,数据插入成功但页面并不能显示 # 基于ajax提交的表单数据处理 def ajax(request): ret = {'status': True, 'error': None, 'data': None} # 建议:永远让服务器端返回一个字典 try: h = request.POST.get('hostname') i = request.POST.get('ip') p = request.POST.get('port') b = request.POST.get('b_id') if h and len(h) > 5: models.Host.objects.create(hostname=h,ip=i,port=p,b_id=b) else: ret['status'] = False ret['error'] = "not long enough" except Exception as e: ret['status'] = False ret['error'] = 'Quest err' return HttpResponse(json.dumps(ret)) # 注意使用 HttpResponse 返回字符串,需要将字典序列化
=== host.html ===
<!DOCTYPE html><html lang="en"><head>
<meta charset="UTF-8"> <title></title> <style> .hide{ display: none; } .shade{ position: fixed; top: 0; right: 0; left: 0; bottom: 0; background: black; opacity: 0.6; z-index: 100; } .add-modal,.edit-modal{ position: fixed; height: 300px; width: 400px; top:100px; left: 50%; z-index: 101; border: 1px solid red; background: white; margin-left: -200px; } </style> </head> <body> <h1>主机列表(对象)</h1> <div> <input id="add_host" type="button" value="添加" /> </div> <table border="1"> <thead> <tr> <th>序号</th> <th>主机名</th> <th>IP</th> <th>端口</th> <th>业务线名称</th> <th>操作</th> </tr> </thead> <tbody> {% for row in v1 %} <tr hid="{{ row.nid }}" bid="{{ row.b_id }}"> <td>{{ forloop.counter }}</td> <!-- 计数器 counter,counter0,revcounter,revcounter0,first,last, parentcounter --> <td>{{ row.hostname }}</td> <td>{{ row.ip }}</td> <td>{{ row.port }}</td> <td>{{ row.b.caption }}</td> <td> <a class="edit">编辑</a>|<a class="delete">删除</a> </td> </tr> {% endfor %} </tbody> </table> <h1>主机列表(字典)</h1> <table border="1"> <thead> <tr> <th>主机名</th> <th>业务线名称</th> </tr> </thead> <tbody> {% for row in v2 %} <tr hid="{{ row.nid }}" bid="{{ row.b_id }}"> <td>{{ row.hostname }}</td> <td>{{ row.b__caption }}</td> </tr> {% endfor %} </tbody> </table> <h1>主机列表(元组)</h1> <table border="1"> <thead> <tr> <th>主机名</th> <th>业务线名称</th> </tr> </thead> <tbody> {% for row in v3 %} <tr hid="{{ row.0 }}" bid="{{ row.2 }}"> <td>{{ row.1 }}</td> <td>{{ row.3 }}</td> </tr> {% endfor %} </tbody> </table> <div class="shade hide"></div> <div class="add-modal hide"> <form id="add_form" method="POST" action="/host"> <div class="group"> <input id="host" type="text" placeholder="主机名" name="hostname" /> </div> <div class="group"> <input id="ip" type="text" placeholder="IP" name="ip" /> </div> <div class="group"> <input id="port" type="text" placeholder="端口" name="port" /> </div> <div class="group"> <select id="sel" name="b_id"> {% for op in b_list %} <option value="{{ op.id }}">{{ op.caption }}</option> {% endfor %} </select> </div> <input type="submit" value="提交" /> <a id="ajax_submit" > Ajax </a> <input id="cancel" type="button" value="取消" /> <span id="erro_msg" style="color: red"></span> </form> </div> <script src="/static/jquery-1.12.4.js"></script> <script> $(function(){ // 基于action的 Form表单提交,提交后刷新页面 $('#add_host').click(function(){ $('.shade,.add-modal').removeClass('hide'); }); // 使用Ajax 提交数据,根据服务器端返回的数据做逻辑判断 $('#ajax_submit').click(function(){ $.ajax({ url: "/ajax", type: 'POST', data: $('#add_form').serialize(), // 将form表单的所有数据发给服务器端 | data: {'hostname': $('#host ').val(), 'ip': $('#ip').val(), 'port': $('#port').val(), 'b_id': $('#sel').val()}, success: function(data){ // 这里的data为服务端返回的数据 var obj = JSON.parse(data); // 将字符串转换成对象 if(obj.status){ location.reload(); // 重新加载页面 }else{ $('#erro_msg').text(obj.error); } } }) }); $('#cancel').click(function(){ $('.shade,.add-modal').addClass('hide'); }); $('.edit').click(function(){ $('.shade,.edit-modal').removeClass('hide'); var bid = $(this).parent().parent().attr('bid'); // 获取业务线id var nid = $(this).parent().parent().attr('hid'); $('#edit_form').find('select').val(bid); // 设置业务线的id $('#edit_form').find('input[name="nid"]').val(nid); /* $.ajax({ data: $('#edit_form').serialize() }); */ // models.Host.objects.filter(nid=nid).update() }) }) </script> </body> </html>
多对多
在多对多关系中,A 表中的一行可以匹配 B 表中的多行,反之亦然。要创建这种关系,需要定义第三个表,称为结合表,它的主键由 A 表和 B 表的外部键组成。
如:主机表 Host 和 应用程序表 Application具有多对多关系,一台主机可能跑多个应用程序,一个应用程序可能在多台主机上运行。HostToApp为结合表,Host和Application分别与HostToApp具有一对多的关系。
创建多对多关系数据表
方式一:自定义关系表
#=== models.py === from django.db import models class Business(models.Model): # id caption = models.CharField(max_length=32) code = models.CharField(max_length=32,null=True,default="SA") class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32,db_index=True) ip = models.GenericIPAddressField(protocol="ipv4",db_index=True) port = models.IntegerField() b = models.ForeignKey(to="Business", to_field='id') class Application(models.Model): name = models.CharField(max_length=32) class HostToApp(models.Model): H = models.ForeignKey(to='Host',to_field='nid') A = models.ForeignKey(to='Application',to_field='id')
# 可以自定义多个字段
方式二:自动创建关系表
from django.db import models # Create your models here. class Business(models.Model): # id caption = models.CharField(max_length=32) code = models.CharField(max_length=32,null=True,default="SA") fk = models.ForeignKey('Foo') class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32,db_index=True) ip = models.GenericIPAddressField(protocol="ipv4",db_index=True) port = models.IntegerField() b = models.ForeignKey(to="Business", to_field='id') class Application(models.Model): name = models.CharField(max_length=32) r = models.ManyToManyField("Host")
# 用两个类创建了三张表 ,第三张表最多生成3个字段
自动创建的关系表无法直接对第三张表操作,但可以进行间接操作:
obj = Application.objects.get(id=1)
# 操作name字段
obj.name
# 操作第三张表
obj.r.add(1) # 在第三张表中增加 id=1,nid=1
obj.r.add(2) # 在第三张表中增加 id=1,nid=2
obj.r.add(1,2) 或 obj.r.add(*[1,2]) # 同时增加多个关系
obj.r.remove(1)
obj.r.remove(1,2) 或 obj.r.remove(*[1,2]) # 同时删除多个关系
obj.r.clear() # 清除所有aid=1的关联
obj.r.set([3,5,7]) # 设置某几个关联,即update语句
obj.r.all() # QuerySet,所有相关的主机对象
建议:两种方式都用
示例:添加应用程序
#=== views.py ===
from django.shortcuts import render,HttpResponse,redirect from app01 import models import json # 基于action提交Form表单数据的处理 def app(request): if request.method == "GET": app_list = models.Application.objects.all() # for row in app_list: # print(row.name,row.r.all()) host_list = models.Host.objects.all() return render(request,'app.html',{"app_list": app_list,'host_list': host_list}) elif request.method == "POST": app_name = request.POST.get('app_name') host_list = request.POST.getlist('host_list') print(app_name,host_list) obj = models.Application.objects.create(name=app_name) obj.r.add(*host_list) return redirect('/app') # 基于ajax提交的表单数据处理
def ajax_add_app(request): ret = {'status':True, 'error':None, 'data': None} app_name = request.POST.get('app_name') host_list = request.POST.getlist('host_list') obj = models.Application.objects.create(name=app_name) obj.r.add(*host_list) return HttpResponse(json.dumps(ret))
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <style> .host-tag{ display: inline-block; padding: 3px; border: 1px solid red; background-color: palevioletred; } .hide{ display: none; } .shade{ position: fixed; top: 0; right: 0; left: 0; bottom: 0; background: black; opacity: 0.6; z-index: 100; } .add-modal,.edit-modal{ position: fixed; height: 300px; width: 400px; top:100px; left: 50%; z-index: 101; border: 1px solid red; background: white; margin-left: -200px; } </style> </head> <body> <h1>应用列表</h1> <div> <input id="add_app" type="button" value="添加" /> </div> <table border="1"> <thead> <tr> <td>应用名称</td> <td>应用主机列表</td> </tr> </thead> <tbody> {% for app in app_list %} <tr aid="{{ app.id }}"> <td>{{ app.name }}</td> <!-- <td>{{ app.r.all }}</td> --> <td> {% for host in app.r.all %} <span class="host-tag" hid="{{ host.nid }}"> {{ host.hostname }} </span> {% endfor %} </td> <td> <a class="edit">编辑</a> </td> </tr> {% endfor %} </tbody> </table> <div class="shade hide"></div> <div class="add-modal hide"> <form id="add_form" method="POST" action="/app"> <div class="group"> <input id="app_name" type="text" placeholder="应用名称" name="app_name" /> </div> <div class="group"> <select id="host_list" name="host_list" multiple> {% for op in host_list %} <option value="{{ op.nid }}">{{ op.hostname }}</option> {% endfor %} </select> </div> <input type="submit" value="提交" /> <input id="add_submit_ajax" type="button" value="Ajax提交" /> </form> </div> <div class="edit-modal hide"> <form id="edit_form" method="POST" action="/host"> <input type="text" name="nid" style="display:none" /> <input type="text" placeholder="应用名称" name="app" /> <select name="host_list" multiple> {% for op in host_list %} <option value="{{ op.nid }}">{{ op.hostname }}</option> {% endfor %} </select> <a id="ajax_submit_edit" >确认编辑</a> </form> </div> <script src="/static/jquery-1.12.4.js"></script> <script> $(function(){ $('#add_app').click(function(){ $('.shade,.add-modal').removeClass('hide'); }); $('#cancel').click(function(){ $('.shade,.add-modal').addClass('hide'); }); $('#add_submit_ajax').click(function(){ $.ajax({ url: '/ajax_add_app', // data: {'user': 123,'host_list': [1,2,3,4]}, data: $('#add_form').serialize(), traditional: true, // data: {'user': 123,'host_list': [1,2,3,4]}, 后台可以获取到列表 type: "POST", dataType: 'JSON', // success: function(obj){ // 此处不是字符串,返回一个对象 console.log(obj); }, error: function () { // 当后台发生未知错误时执行 } }) }); $('.edit').click(function(){ $('.edit-modal,.shade').removeClass('hide'); var hid_list = []; $(this).parent().prev().children().each(function(){ var hid = $(this).attr('hid'); hid_list.push(hid) // 追加 }); $('#edit_form').find('select').val(hid_list); /* 如果发送到后台 obj = models.Application.objects.get(id=ai) obj.name = "新Name" obj.save() obj.r.set([1,2,3,4]) */ }) }) </script> </body> </html>
添加编辑的两种应用场景
1、模态对话框: 当数据量比较大时不适合用
2、新URL:博客园添加博客
ORM 反向查询
https://www.cnblogs.com/sss4/p/7070942.html
https://www.cnblogs.com/mosson/p/5806823.html