上一篇博文簡述了Django ORM的單表操做,在本篇博文中主要簡述Django ORM的連表操做。javascript
應用場景:當一張表中建立一行數據時,有一個單選的下拉框(能夠被重複選擇), 例如:建立用戶信息時候,須要選擇一個用戶類型【普通用戶】【金牌用戶】【鉑金用戶】等html
1 ForeignKey(ForeignObject) # ForeignObject(RelatedField) 2 to, # 要進行關聯的表名 3 to_field=None, # 要關聯的表中的字段名稱 4 on_delete=None, # 當刪除關聯表中的數據時,當前表與其關聯的行的行爲 5 - models.CASCADE,刪除關聯數據,與之關聯也刪除 6 - models.DO_NOTHING,刪除關聯數據,引起錯誤IntegrityError 7 - models.PROTECT,刪除關聯數據,引起錯誤ProtectedError 8 - models.SET_NULL,刪除關聯數據,與之關聯的值設置爲null(前提FK字段須要設置爲可空) 9 - models.SET_DEFAULT,刪除關聯數據,與之關聯的值設置爲默認值(前提FK字段須要設置默認值) 10 - models.SET,刪除關聯數據, 11 a. 與之關聯的值設置爲指定值,設置:models.SET(值) 12 b. 與之關聯的值設置爲可執行對象的返回值,設置:models.SET(可執行對象) 13 14 def func(): 15 return 10 16 17 class MyModel(models.Model): 18 user = models.ForeignKey( 19 to="User", 20 to_field="id" 21 on_delete=models.SET(func),) 22 related_name=None, # 反向操做時,使用的字段名,用於代替 【表名_set】 如: obj.表名_set.all() 23 related_query_name=None, # 反向操做時,使用的鏈接前綴,用於替換【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名') 24 limit_choices_to=None, # 在Admin或ModelForm中顯示關聯數據時,提供的條件: 25 # 如: 26 - limit_choices_to={'nid__gt': 5} 27 - limit_choices_to=lambda : {'nid__gt': 5} 28 29 from django.db.models import Q 30 - limit_choices_to=Q(nid__gt=10) 31 - limit_choices_to=Q(nid=8) | Q(nid__gt=10) 32 - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') 33 db_constraint=True # 是否在數據庫中建立外鍵約束 34 parent_link=False # 在Admin中是否顯示關聯數據 35 36 models.ForeignKey()函數的主要參數
1 一對多: 2 def func(): 3 4 return 5 5 6 7 class UserType(models.Model): 8 name = models.CharField(max_length=32) 9 10 11 class User(models.Model): 12 name = models.CharField(max_length=32) 13 pwd = models.CharField(max_length=32) 14 ut = models.ForeignKey(to="UserType",to_field='id',on_delete=models.SET(func)) 15 16 # delete from user where id=1 17 # delete from UserType where id=1 # 報錯 18 19 # UserType.objects.filter(id=1).delete() 20 21 22 23 # 正向 24 # v = User.objects.all() 25 # for item in v: 26 # item.user 27 # item.pwd 28 # item.ut.name 29 # User.objects.all().values('user','ut__name') 30 31 # 反向 32 # v = UserType.objects.all() 33 # for item in v: 34 # item.name 35 # item.id 36 # item.user_set.all() #user_set是經過對象進行反向查找 37 # models.UserType.objects.all().values('name','user__pwd') #user_pwd是在values中經過pwd條件進行反向查找 38 39 ### related_name演示: 40 #添加related_name參數後 41 ut = models.ForeignKey(to="UserType",to_field='id',on_delete=models.SET(func),related_name="a") 42 #經過對象進行反向查找,將會"a"進行替代「表名_set」 43 item.a.all() #替換item.user_set.all() 44 45 related_query_name演示: 46 #添加related_query_name參數後 47 ut = models.ForeignKey(to="UserType",to_field='id',on_delete=models.SET(func),related_query_name="b") 48 #對象反向查找,將會"b_set"進行替代「表名_set」,條件反向查詢時,將會以「b_字段"代替表名"字段" 49 item.b_set.all() #替換item.user_set.all() 50 models.UserType.objects.all().values('name','b__pwd') #替換models.UserType.ob jects.all().values('name','user__pwd')
一、建立一對多表結構:前端
from django.db import models class Business(models.Model): caption = models.CharField(max_length=32) code = models.CharField(max_length=32) class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32, db_index=True) # 默認爲protocol="both",即支持ipv4,也支持ipv協議 ip = models.GenericIPAddressField(protocol="ipv4", db_index=True) port = models.IntegerField() # on_delete=models.SET_NULL 意思爲:可爲空的 ForeignKey ,他引用關聯的對象被刪除時,該項爲空,前提是set null=True b = models.ForeignKey(to="Business", to_field='id', null=True, on_delete=models.SET_NULL)
二、一對多表結構操做示例:java
在前端頁面對host列表進行主機展現、添加、編輯、刪除管理,從而演示一對多表結構的增刪查改操做。python
一、app中的urls.py:jquery
1 from django.conf.urls import url 2 from app1 import views 3 urlpatterns = [ 4 url(r'^host$', views.host), 5 url(r'^test_ajax$', views.test_ajax), 6 url(r'^edit$', views.edit), 7 url(r'^del$', views.delete), 8 ]
二、templates:ajax
爲了演示方便,沒有對host.html進行結構、樣式相分離的操做(行爲已分離)。數據庫
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 <style> 7 .hide { 8 display: none; 9 } 10 11 .shade { 12 position: fixed; 13 top: 0; 14 right: 0; 15 left: 0; 16 bottom: 0; 17 background: black; 18 opacity: 0.6; 19 z-index: 100; 20 } 21 22 .add-modal, .edit-modal { 23 position: fixed; 24 height: 300px; 25 width: 400px; 26 top: 100px; 27 left: 50%; 28 z-index: 101; 29 border: 1px solid red; 30 background: white; 31 margin-left: -200px; 32 } 33 </style> 34 </head> 35 <body> 36 <h1>主機列表(對象)</h1> 37 38 <div> 39 <input id="add_host" type="button" value="添加"/> 40 </div> 41 <table border="1"> 42 <thead> 43 <tr> 44 <th>序號</th> 45 <th>主機名</th> 46 <th>IP</th> 47 <th>端口</th> 48 <th>業務線名稱</th> 49 <th>操做</th> 50 </tr> 51 </thead> 52 <tbody> 53 54 {% for row in v1 %} 55 <tr h_id="{{ row.nid }}" b_id="{{ row.b_id }}"> 56 <td>{{ forloop.counter }}</td> 57 <td>{{ row.hostname }}</td> 58 <td>{{ row.ip }}</td> 59 <td>{{ row.port }}</td> 60 <td>{{ row.b.caption }}</td> 61 <td> 62 <a class="edit">編輯</a>|<a class="delete">刪除</a> 63 </td> 64 </tr> 65 {% endfor %} 66 67 68 </tbody> 69 </table> 70 71 <h1>主機列表(字典)</h1> 72 <table border="1"> 73 <thead> 74 <tr> 75 <th>主機名</th> 76 <th>業務線名稱</th> 77 </tr> 78 </thead> 79 <tbody> 80 {% for row in v2 %} 81 <tr hid="{{ row.nid }}" bid="{{ row.b_id }}"> 82 <td>{{ row.hostname }}</td> 83 <td>{{ row.b__caption }}</td> 84 </tr> 85 {% endfor %} 86 87 </tbody> 88 </table> 89 <h1>主機列表(元組)</h1> 90 <table border="1"> 91 <thead> 92 <tr> 93 <th>主機名</th> 94 <th>業務線名稱</th> 95 </tr> 96 </thead> 97 <tbody> 98 {% for row in v3 %} 99 <tr hid="{{ row.0 }}" bid="{{ row.2 }}"> 100 <td>{{ row.1 }}</td> 101 <td>{{ row.3 }}</td> 102 </tr> 103 {% endfor %} 104 105 </tbody> 106 </table> 107 108 109 <div class="shade hide"></div> 110 <div class="add-modal hide"> 111 <form id="add_form" method="POST" action="/app1/host"> 112 <div class="group"> 113 <input id="host" type="text" placeholder="主機名" name="hostname"/> 114 </div> 115 116 <div class="group"> 117 <input id="ip" type="text" placeholder="IP" name="ip"/> 118 </div> 119 120 <div class="group"> 121 <input id="port" type="text" placeholder="端口" name="port"/> 122 </div> 123 124 <div class="group"> 125 <select id="sel" name="b_id"> 126 {% for op in b_list %} 127 <option value="{{ op.id }}">{{ op.caption }}</option> 128 {% endfor %} 129 </select> 130 </div> 131 132 <input type="submit" value="提交"/> 133 <a id="ajax_submit">悄悄提交</a> 134 <input id="cancel" type="button" value="取消"/> 135 <span id="erro_msg" style="color: red"></span> 136 </form> 137 138 139 </div> 140 141 <div class="edit-modal hide"> 142 <form id="edit_form" method="POST" action="app1/host"> 143 <input type="text" name="nid" style="display:none"/> 144 <input type="text" placeholder="主機名" name="hostname"/> 145 <input type="text" placeholder="IP" name="ip"/> 146 <input type="text" placeholder="端口" name="port"/> 147 <select name="b_id"> 148 {% for op in b_list %} 149 <option value="{{ op.id }}">{{ op.caption }}</option> 150 {% endfor %} 151 </select> 152 <a id="ajax_submit_edit">確認編輯</a> 153 </form> 154 </div> 155 156 157 <script src="/static/jquery-1.12.4.js"></script> 158 <script src="/static/common.js"></script> 159 </body> 160 </html>
三、static:django
在static編寫JavaScript公共函數conmon.js(在編寫common.js以前須要引入jQuery):json
$(function () { //添加操做 $('#add_host').click(function () { $('.shade,.add-modal').removeClass('hide'); }); $('#cancel').click(function () { $('.shade,.add-modal').addClass('hide'); }); $('#ajax_submit').click(function () { $.ajax({ url: "/app1/test_ajax", //url定義ajax發送請求的URL type: 'POST', //type定義ajax發送請求的方法類型 // data中則是ajax準備發送服務端的數據 //data: {'hostname': $('#host').val(), 'ip': $('#ip').val(), 'port': $('#port').val(), 'b_id': $('#sel').val()}, data: $('#add_form').serialize(), // 將整個form表單中的參數以字典形式發送給服務端,相比上面的寫法,更加便捷 success: function (data) { // 服務端返回數據成功後執行的方法 var obj = JSON.parse(data); if (obj.status) { location.reload(); //從新加載當前頁面(get形式) } else { $('#erro_msg').text(obj.error); } } }) }); //編輯操做 $('.edit').click(function () { $('.shade,.edit-modal').removeClass('hide'); var bid = $(this).parent().parent().attr('b_id'); var nid = $(this).parent().parent().attr('h_id'); $('#edit_form').find('select').val(bid); $('#edit_form').find('input[name="nid"]').val(nid); $("#ajax_submit_edit").click(function () { $.ajax({ url: "/app1/edit", type: "POST", data: $('#edit_form').serialize(), success: function (data) { var obj = JSON.parse(data); if (obj.status) { $('.shade,.add-modal,.edit-modal').addClass('hide'); location.reload(); } else { $('#erro_msg').text(obj.error); } } }); }); }) }); //刪除操做 $('.delete').click(function () { var nid = $(this).parent().parent().attr('h_id'); $.ajax({ url: "/app1/del", type: "POST", data: {"nid": nid}, success: function (data) { var obj = JSON.parse(data); if (obj.status) { location.reload(); } } }); });
四、app中的views.py:
import json from django.shortcuts import redirect from django.shortcuts import HttpResponse from django.shortcuts import render from app1 import models def host(request): """ host函數經過request區別get和post方法,若是是request是get方法,就從數據庫中查詢數據,而後將查詢的數據返回給HTML進行渲染展現 若是是request是post方法,就從request中提取數據,而後進行數據庫添加操做 :param request: :return: """ 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 ) return redirect('/app1/host') # 經過ajax方式提交數據,服務端提取數據操做後返回的示例: def test_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'] = "hostname error" except Exception as e: ret['status'] = False ret['error'] = "request error" return HttpResponse(json.dumps(ret)) # 編輯操做 def edit(request): ret = {'status': True, 'error': None, 'data': None} print(request.POST, request.method) try: nid = request.POST.get('nid') h = request.POST.get('hostname') i = request.POST.get('ip') p = request.POST.get('port') b = request.POST.get('b_id') models.Host.objects.filter(nid=nid).update( hostname=h, ip=i, port=p, b_id=b ) except Exception as e: ret['status'] = False ret['error'] = "hostname error" return HttpResponse(json.dumps(ret)) # 刪除操做 def delete(request): ret = {'status': True, 'error': None, 'data': None} print(request.POST) try: nid = request.POST.get('nid') models.Host.objects.filter(nid=nid).delete() except Exception as e: ret['status'] = False ret['error'] = "request error" return HttpResponse(json.dumps(ret))
應用場景:在某表中建立一行數據是,有一個能夠多選的下拉框,例如:建立用戶信息,須要爲用戶指定多個愛好
1 ManyToManyField(RelatedField) 2 to, # 要進行關聯的表名 3 related_name=None, # 反向操做時,使用的字段名,用於代替 【表名_set】 如: obj.表名_set.all() 4 related_query_name=None, # 反向操做時,使用的鏈接前綴,用於替換【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名') 5 limit_choices_to=None, # 在Admin或ModelForm中顯示關聯數據時,提供的條件: 6 # 如: 7 - limit_choices_to={'nid__gt': 5} 8 - limit_choices_to=lambda : {'nid__gt': 5} 9 10 from django.db.models import Q 11 - limit_choices_to=Q(nid__gt=10) 12 - limit_choices_to=Q(nid=8) | Q(nid__gt=10) 13 - limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root') 14 symmetrical=None, # 僅用於多對多自關聯時,symmetrical用於指定內部是否建立反向操做的字段 15 # 作以下操做時,不一樣的symmetrical會有不一樣的可選字段 16 models.BB.objects.filter(...) 17 18 # 可選字段有:code, id, m1 19 class BB(models.Model): 20 21 code = models.CharField(max_length=12) 22 m1 = models.ManyToManyField('self',symmetrical=True) 23 24 # 可選字段有: bb, code, id, m1 25 class BB(models.Model): 26 27 code = models.CharField(max_length=12) 28 m1 = models.ManyToManyField('self',symmetrical=False) 29 30 through=None, # 自定義第三張表時,使用字段用於指定關係表 31 through_fields=None, # 自定義第三張表時,使用字段用於指定關係表中那些字段作多對多關係表 32 from django.db import models 33 34 class Person(models.Model): 35 name = models.CharField(max_length=50) 36 37 class Group(models.Model): 38 name = models.CharField(max_length=128) 39 members = models.ManyToManyField( 40 Person, 41 through='Membership', 42 through_fields=('group', 'person'), 43 ) 44 45 class Membership(models.Model): 46 group = models.ForeignKey(Group, on_delete=models.CASCADE) 47 person = models.ForeignKey(Person, on_delete=models.CASCADE) 48 inviter = models.ForeignKey( 49 Person, 50 on_delete=models.CASCADE, 51 related_name="membership_invites", 52 ) 53 invite_reason = models.CharField(max_length=64) 54 db_constraint=True, # 是否在數據庫中建立外鍵約束 55 db_table=None, # 默認建立第三張表時,數據庫中表的名稱
一、建立多對多表結構:
# 方式一:自定義關係表 (可直接經過類名操做自定義的關係表,且在自定義的關係表中添加任意列名) class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32, db_index=True) # 默認爲protocol="both",即支持ipv4,也支持ipv協議 ip = models.GenericIPAddressField(protocol="ipv4", db_index=True) port = models.IntegerField() class Application(models.Model): name = models.CharField(max_length=32) class HostToApp(models.Model): host = models.ForeignKey(to='Host', to_field='nid', on_delete=models.SET_NULL) application = models.ForeignKey(to='Application', to_field='id', on_delete=models.SET_NULL) # 方式二:由Django自動建立關係表(經過Django建立的關係表,不能夠直接經過類名操做關係表,只能經過間接方式操做表,且Django自動建立表只能默認生成3列數據:id、application_id、host_id) class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32, db_index=True) # 默認爲protocol="both",即支持ipv4,也支持ipv協議 ip = models.GenericIPAddressField(protocol="ipv4", db_index=True) port = models.IntegerField() b = models.ForeignKey(to="Business", to_field='id', null=True, on_delete=models.SET_NULL) class Application(models.Model): name = models.CharField(max_length=32) host = models.ManyToManyField("Host") # 方式三:既自定義關係表,也有Django ManyToManyField創建的m2m字段,但m2m字段只能進行查詢操做,不能進行增刪改操做(支持clear),推薦使用方法三 class Host(models.Model): nid = models.AutoField(primary_key=True) hostname = models.CharField(max_length=32, db_index=True) # 默認爲protocol="both",即支持ipv4,也支持ipv協議 ip = models.GenericIPAddressField(protocol="ipv4", db_index=True) port = models.IntegerField() class Application(models.Model): name = models.CharField(max_length=32) host = models.ManyToManyField("Host", through="Host", through_fields=["host,""application"]) # through 字段是告訴Django經過哪張表進行m2m關聯關係 class HostToApp(models.Model): host = models.ForeignKey(to='Host', to_field='nid', on_delete=models.SET_NULL) application = models.ForeignKey(to='Application', to_field='id', on_delete=models.SET_NULL)
注:Django自動建立關係表的間接操做方式
1 # 經過特定條件的表對象進行關係表操做 2 obj = Application.objects.get(id=1) 3 # 服務應用的名稱 4 obj.name 5 6 # # 關係表操做 7 # 在關係表中添加Application、host(單個服務應用、單個主機)對應關係 對應條件:Application表中id=1(服務應用),host表中id=1(主機) 8 obj.host.add(1) 9 # 在關係表中添加Application、host(單個服務應用、單個主機)對應關係 對應條件:Application表中id=1(服務應用),host表中id=2(主機) 10 obj.host.add(2) 11 # 在關係表中添加Application、host(單個服務應用、多個主機)對應關係 對應條件:Application表中id=1(服務應用),# host表中id=二、id=三、id=4(主機) 12 obj.host.add(2, 3, 4) 13 # 在關係表中添加Application、host(單個服務應用、多個主機列表形式)對應關係 對應條件:Application表中id=1(服務應用),# host表中id=一、id=二、id=三、id=4(主機) 14 obj.host.add(*[1, 2, 3, 4]) 15 16 # 在關係表中移除Application、host(單個服務應用、單個主機)對應關係 對應條件:Application表中id=1(服務應用),host表中id=1(主機) 17 obj.host.remove(1) 18 # 在關係表中移除Application、host(單個服務應用、多個主機)對應關係 對應條件:Application表中id=1(服務應用),host表中id=二、id=4(主機) 19 obj.host.remove(2, 4) 20 # 在關係表中移除Application、host(單個服務應用、多個主機列表形式)對應關係 對應條件:Application表中id=1(服務應用),# host表中id=一、id=二、id=三、id=4(主機) 21 obj.host.remove(*[1, 2, 3]) 22 23 # 在關係表中清除Application、host(單個服務應用、單個/多個主機)對應關係 條件:將關係表中Application id=1(服務應用)對應單個/多個主機關係所有清除 24 obj.host.clear() 25 26 # set()有些特殊,在關係表中設置對應關係以前,會將以前關係表中,Application id=1(服務應用)全部host(主機)對應關係清除 27 # 在關係表中設置Application、host(單個服務應用、多個主機列表形式)對應關係 對應條件:Application表中id=1(服務應用),# host表中id=一、id=二、id=3(主機) 28 obj.host.set([1, 2, 3]) 29 30 # 所相關的主機對象QuerySet 31 obj.host.all()
二、多對多表結構操做示例
在前端頁面對app(服務應用)、host(主機)列表進行展現、添加、編輯、刪除管理,從而演示一對多表結構的增刪查改操做
一、app中的urls.py:
1 from django.conf.urls import url 2 from app1 import views 3 urlpatterns = [ 4 url(r'^app$', views.app), 5 url(r'^ajax_add_app$', views.ajax_add_app), 6 url(r'^ajax_submit_edit$', views.ajax_submit_edit), 7 url(r'^ajax_submit_delete$', views.ajax_submit_delete), 8 9 ]
二、templates:
爲了演示方便,沒有對host.html進行結構、樣式相分離的操做(行爲已分離)。
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title></title> 6 <style> 7 .host-tag { 8 display: inline-block; 9 padding: 3px; 10 border: 1px solid red; 11 background-color: palevioletred; 12 } 13 14 .hide { 15 display: none; 16 } 17 18 .shade { 19 position: fixed; 20 top: 0; 21 right: 0; 22 left: 0; 23 bottom: 0; 24 background: black; 25 opacity: 0.6; 26 z-index: 100; 27 } 28 29 .add-modal, .edit-modal { 30 position: fixed; 31 height: 300px; 32 width: 400px; 33 top: 100px; 34 left: 50%; 35 z-index: 101; 36 border: 1px solid red; 37 background: white; 38 margin-left: -200px; 39 } 40 </style> 41 </head> 42 <body> 43 44 <h1>應用列表</h1> 45 46 <div> 47 <input id="add_app" type="button" value="添加"/> 48 </div> 49 <table border="1"> 50 <thead> 51 <tr> 52 <td>應用名稱</td> 53 <td>應用主機列表</td> 54 <td>操做</td> 55 </tr> 56 </thead> 57 <tbody> 58 {% for app in app_list %} 59 <tr aid="{{ app.id }}"> 60 <td>{{ app.name }}</td> 61 <td> 62 {% for host in app.host.all %} 63 <span class="host-tag" hid="{{ host.nid }}"> {{ host.hostname }} </span> 64 {% endfor %} 65 </td> 66 <td> 67 <a class="edit">編輯</a>|<a class="delete">刪除</a> 68 </td> 69 </tr> 70 {% endfor %} 71 </tbody> 72 </table> 73 74 75 <div class="shade hide"></div> 76 <div class="add-modal hide"> 77 <form id="add_form" method="POST" action="/app1/app"> 78 <div class="group"> 79 <input id="app_name" type="text" placeholder="應用名稱" name="app_name"/> 80 </div> 81 <div class="group"> 82 <select id="host_list" name="host_list" multiple> 83 {% for op in host_list %} 84 <option value="{{ op.nid }}">{{ op.hostname }}</option> 85 {% endfor %} 86 </select> 87 </div> 88 89 <input id="add_submit" type="submit" value="提交"/> 90 <input id="add_submit_ajax" type="button" value="Ajax提交"/> 91 </form> 92 93 94 </div> 95 96 <div class="edit-modal hide"> 97 <form id="edit_form" method="POST" action="/host"> 98 <input type="text" name="nid" style="display:none"/> 99 <input type="text" placeholder="應用名稱" name="app"/> 100 <select name="host_list" multiple> 101 {% for op in host_list %} 102 <option value="{{ op.nid }}">{{ op.hostname }}</option> 103 {% endfor %} 104 </select> 105 <a id="ajax_submit_edit">確認編輯</a> 106 </form> 107 108 109 </div> 110 111 <script src="/static/jquery-1.12.4.js"></script> 112 <script src="/static/common.js"></script> 113 </body> 114 </html>
三、static:
在static編寫JavaScript公共函數conmon.js(在編寫common.js以前須要引入jQuery):
$(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: '/app1/ajax_add_app', // data: {'user': 123,'host_list': [1,2,3,4]}, data: $('#add_form').serialize(), type: "POST", dataType: 'JSON', //dataType定義爲JSON後,就不用再對服務端返回的數據進行反序列化 traditional: true, // traditional定義true後,才能支持data列表形式的value請求參數: {''host_list': [1,2,3,4]} success: function (obj) { if (obj.status) { $('.shade,.add-modal').addClass('hide'); location.reload(); } }, 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); var aid = $(this).parent().siblings(":first").text(); $('#edit_form').find('input[name="app"]').val(aid); var nid = $(this).parent().parent().attr("aid"); console.log(nid); $('#edit_form').find('input[name="nid"]').val(nid); $("#ajax_submit_edit").click(function () { $.ajax({ url: "/app1/ajax_submit_edit", type: "POST", data: $("#edit_form").serialize(), dataType: "JSON", success: function (data) { if (data.status) { $('.shade,.edit-modal').addClass('hide'); location.reload(); } } }) }); }); //刪除操做 $('.delete').click(function () { var hid_list = []; $(this).parent().prev().children().each(function () { var hid = $(this).attr('hid'); hid_list.push(hid) }); console.log(hid_list); var nid = $(this).parent().parent().attr("aid"); console.log(nid); $.ajax({ url: "/app1/ajax_submit_delete", type: "POST", data: {"nid": nid, "host_id_list": hid_list}, dataType: "JSON", traditional: true, success: function (data) { if (data.status) { location.reload(); } } }); }); })
四、app中的views.py:
import json from django.shortcuts import redirect from django.shortcuts import HttpResponse from django.shortcuts import render from app1 import models # form提交數據添加操做 def app(request): """ host函數經過request區別get和post方法,若是是request是get方法,就從數據庫中查詢數據,而後將查詢的數據返回給HTML進行渲染展現 若是是request是post方法,就從request中提取數據,而後進行數據庫添加操做 :param request: :return: """ if request.method == "GET": app_list = models.Application.objects.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.host.add(*host_list) return redirect('/app1/app') # ajax提交數據添加操做 def ajax_add_app(request): ret = {'status': True, 'error': None, 'data': None} print(request.POST) try: 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.host.add(*host_list) except Exception as e: ret['status'] = False ret['error'] = "request error" return HttpResponse(json.dumps(ret)) # 編輯操做 def ajax_submit_edit(request): ret = {'status': True, 'error': None, 'data': None} print(request.POST) try: nid = request.POST.get("nid") app_name = request.POST.get("app") host_list = request.POST.getlist('host_list') print(app_name, host_list) obj = models.Application.objects.get(id=nid) obj.name = app_name obj.save() obj.host.set(host_list) except Exception as e: ret['status'] = False ret['error'] = "request error" return HttpResponse(json.dumps(ret)) # 刪除操做 def ajax_submit_delete(request): ret = {'status': True, 'error': None, 'data': None} print(request.POST) try: nid = request.POST.get("nid") host_list = request.POST.getlist('host_id_list') print(nid, host_list) obj = models.Application.objects.get(id=nid) obj.host.remove(*host_list) models.Application.objects.filter(id=nid).delete() except Exception as e: ret['status'] = False ret['error'] = "request error" return HttpResponse(json.dumps(ret))