Django ORM(进阶)

上一篇博文简述了Django ORM的单表操作,在本篇博文中主要简述Django ORM的连表操作。

一、一对多:models.ForeignKey()

应用场景:当一张表中创建一行数据时,有一个单选的下拉框(可以被重复选择), 例如:创建用户信息时候,需要选择一个用户类型【普通用户】【金牌用户】【铂金用户】等

 ForeignKey(ForeignObject) # ForeignObject(RelatedField)
to, # 要进行关联的表名
to_field=None, # 要关联的表中的字段名称
on_delete=None, # 当删除关联表中的数据时,当前表与其关联的行的行为
- models.CASCADE,删除关联数据,与之关联也删除
- models.DO_NOTHING,删除关联数据,引发错误IntegrityError
- models.PROTECT,删除关联数据,引发错误ProtectedError
- models.SET_NULL,删除关联数据,与之关联的值设置为null(前提FK字段需要设置为可空)
- models.SET_DEFAULT,删除关联数据,与之关联的值设置为默认值(前提FK字段需要设置默认值)
- models.SET,删除关联数据,
a. 与之关联的值设置为指定值,设置:models.SET(值)
b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象) def func():
return 10 class MyModel(models.Model):
user = models.ForeignKey(
to="User",
to_field="id"
on_delete=models.SET(func),)
related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件:
# 如:
- limit_choices_to={'nid__gt': 5}
- limit_choices_to=lambda : {'nid__gt': 5} from django.db.models import Q
- limit_choices_to=Q(nid__gt=10)
- limit_choices_to=Q(nid=8) | Q(nid__gt=10)
- limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
db_constraint=True # 是否在数据库中创建外键约束
parent_link=False # 在Admin中是否显示关联数据 models.ForeignKey()函数的主要参数

models.ForeignKey()函数的主要参数

 一对多:
def func(): return 5 class UserType(models.Model):
name = models.CharField(max_length=32) class User(models.Model):
name = models.CharField(max_length=32)
pwd = models.CharField(max_length=32)
ut = models.ForeignKey(to="UserType",to_field='id',on_delete=models.SET(func)) # delete from user where id=1
# delete from UserType where id=1 # 报错 # UserType.objects.filter(id=1).delete() # 正向
# v = User.objects.all()
# for item in v:
# item.user
# item.pwd
# item.ut.name
# User.objects.all().values('user','ut__name') # 反向
# v = UserType.objects.all()
# for item in v:
# item.name
# item.id
# item.user_set.all() #user_set是通过对象进行反向查找
# models.UserType.objects.all().values('name','user__pwd') #user_pwd是在values中通过pwd条件进行反向查找 ### related_name演示:
#添加related_name参数后
ut = models.ForeignKey(to="UserType",to_field='id',on_delete=models.SET(func),related_name="a")
#通过对象进行反向查找,将会"a"进行替代“表名_set”
item.a.all() #替换item.user_set.all() related_query_name演示:
#添加related_query_name参数后
ut = models.ForeignKey(to="UserType",to_field='id',on_delete=models.SET(func),related_query_name="b")
#对象反向查找,将会"b_set"进行替代“表名_set”,条件反向查询时,将会以“b_字段"代替表名"字段"
item.b_set.all() #替换item.user_set.all()
models.UserType.objects.all().values('name','b__pwd') #替换models.UserType.ob jects.all().values('name','user__pwd')

正向、反向查询、related演示

1、创建一对多表结构:

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)

 2、一对多表结构操作示例:

在前端页面对host列表进行主机展示、添加、编辑、删除管理,从而演示一对多表结构的增删查改操作。

1、app中的urls.py:

 from django.conf.urls import url
from app1 import views
urlpatterns = [
url(r'^host$', views.host),
url(r'^test_ajax$', views.test_ajax),
url(r'^edit$', views.edit),
url(r'^del$', views.delete),
]

app中urls.py的路由规则

2、templates:

为了演示方便,没有对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="">
<thead>
<tr>
<th>序号</th>
<th>主机名</th>
<th>IP</th>
<th>端口</th>
<th>业务线名称</th>
<th>操作</th>
</tr>
</thead>
<tbody> {% for row in v1 %}
<tr h_id="{{ row.nid }}" b_id="{{ row.b_id }}">
<td>{{ forloop.counter }}</td>
<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="">
<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="">
<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="/app1/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">悄悄提交</a>
<input id="cancel" type="button" value="取消"/>
<span id="erro_msg" style="color: red"></span>
</form> </div> <div class="edit-modal hide">
<form id="edit_form" method="POST" action="app1/host">
<input type="text" name="nid" style="display:none"/>
<input type="text" placeholder="主机名" name="hostname"/>
<input type="text" placeholder="IP" name="ip"/>
<input type="text" placeholder="端口" name="port"/>
<select name="b_id">
{% for op in b_list %}
<option value="{{ op.id }}">{{ op.caption }}</option>
{% endfor %}
</select>
<a id="ajax_submit_edit">确认编辑</a>
</form>
</div> <script src="/static/jquery-1.12.4.js"></script>
<script src="/static/common.js"></script>
</body>
</html>

host.html

3、static:

在static编写JavaScript公共函数conmon.js(在编写common.js之前需要引入jQuery):

$(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();
}
}
});
});

4、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))

  

二、多对多:models.ManyToManyField()

应用场景:在某表中创建一行数据是,有一个可以多选的下拉框,例如:创建用户信息,需要为用户指定多个爱好

  ManyToManyField(RelatedField)
to, # 要进行关联的表名
related_name=None, # 反向操作时,使用的字段名,用于代替 【表名_set】 如: obj.表名_set.all()
related_query_name=None, # 反向操作时,使用的连接前缀,用于替换【表名】 如: models.UserGroup.objects.filter(表名__字段名=1).values('表名__字段名')
limit_choices_to=None, # 在Admin或ModelForm中显示关联数据时,提供的条件:
# 如:
- limit_choices_to={'nid__gt': 5}
- limit_choices_to=lambda : {'nid__gt': 5} from django.db.models import Q
- limit_choices_to=Q(nid__gt=10)
- limit_choices_to=Q(nid=8) | Q(nid__gt=10)
- limit_choices_to=lambda : Q(Q(nid=8) | Q(nid__gt=10)) & Q(caption='root')
symmetrical=None, # 仅用于多对多自关联时,symmetrical用于指定内部是否创建反向操作的字段
# 做如下操作时,不同的symmetrical会有不同的可选字段
models.BB.objects.filter(...) # 可选字段有:code, id, m1
class BB(models.Model): code = models.CharField(max_length=12)
m1 = models.ManyToManyField('self',symmetrical=True) # 可选字段有: bb, code, id, m1
class BB(models.Model): code = models.CharField(max_length=12)
m1 = models.ManyToManyField('self',symmetrical=False) through=None, # 自定义第三张表时,使用字段用于指定关系表
through_fields=None, # 自定义第三张表时,使用字段用于指定关系表中那些字段做多对多关系表
from django.db import models class Person(models.Model):
name = models.CharField(max_length=50) class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(
Person,
through='Membership',
through_fields=('group', 'person'),
) class Membership(models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE)
person = models.ForeignKey(Person, on_delete=models.CASCADE)
inviter = models.ForeignKey(
Person,
on_delete=models.CASCADE,
related_name="membership_invites",
)
invite_reason = models.CharField(max_length=64)
db_constraint=True, # 是否在数据库中创建外键约束
db_table=None, # 默认创建第三张表时,数据库中表的名称

models.ManyToManyField()函数的主要参数

1、创建多对多表结构:

# 方式一:自定义关系表 (可直接通过类名操作自定义的关系表,且在自定义的关系表中添加任意列名)
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自动创建关系表的间接操作方式

 # 通过特定条件的表对象进行关系表操作
obj = Application.objects.get(id=1)
# 服务应用的名称
obj.name # # 关系表操作
# 在关系表中添加Application、host(单个服务应用、单个主机)对应关系 对应条件:Application表中id=1(服务应用),host表中id=1(主机)
obj.host.add(1)
# 在关系表中添加Application、host(单个服务应用、单个主机)对应关系 对应条件:Application表中id=1(服务应用),host表中id=2(主机)
obj.host.add(2)
# 在关系表中添加Application、host(单个服务应用、多个主机)对应关系 对应条件:Application表中id=1(服务应用),# host表中id=2、id=3、id=4(主机)
obj.host.add(2, 3, 4)
# 在关系表中添加Application、host(单个服务应用、多个主机列表形式)对应关系 对应条件:Application表中id=1(服务应用),# host表中id=1、id=2、id=3、id=4(主机)
obj.host.add(*[1, 2, 3, 4]) # 在关系表中移除Application、host(单个服务应用、单个主机)对应关系 对应条件:Application表中id=1(服务应用),host表中id=1(主机)
obj.host.remove(1)
# 在关系表中移除Application、host(单个服务应用、多个主机)对应关系 对应条件:Application表中id=1(服务应用),host表中id=2、id=4(主机)
obj.host.remove(2, 4)
# 在关系表中移除Application、host(单个服务应用、多个主机列表形式)对应关系 对应条件:Application表中id=1(服务应用),# host表中id=1、id=2、id=3、id=4(主机)
obj.host.remove(*[1, 2, 3]) # 在关系表中清除Application、host(单个服务应用、单个/多个主机)对应关系 条件:将关系表中Application id=1(服务应用)对应单个/多个主机关系全部清除
obj.host.clear() # set()有些特殊,在关系表中设置对应关系之前,会将之前关系表中,Application id=1(服务应用)所有host(主机)对应关系清除
# 在关系表中设置Application、host(单个服务应用、多个主机列表形式)对应关系 对应条件:Application表中id=1(服务应用),# host表中id=1、id=2、id=3(主机)
obj.host.set([1, 2, 3]) # 所相关的主机对象QuerySet
obj.host.all()

关系表的间接操作方式

2、多对多表结构操作示例

在前端页面对app(服务应用)、host(主机)列表进行展示、添加、编辑、删除管理,从而演示一对多表结构的增删查改操作

1、app中的urls.py:

 from django.conf.urls import url
from app1 import views
urlpatterns = [
url(r'^app$', views.app),
url(r'^ajax_add_app$', views.ajax_add_app),
url(r'^ajax_submit_edit$', views.ajax_submit_edit),
url(r'^ajax_submit_delete$', views.ajax_submit_delete), ]

app中urls.py的路由规则

2、templates:

为了演示方便,没有对host.html进行结构、样式相分离的操作(行为已分离)。

 <!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>
<td>操作</td>
</tr>
</thead>
<tbody>
{% for app in app_list %}
<tr aid="{{ app.id }}">
<td>{{ app.name }}</td>
<td>
{% for host in app.host.all %}
<span class="host-tag" hid="{{ host.nid }}"> {{ host.hostname }} </span>
{% endfor %}
</td>
<td>
<a class="edit">编辑</a>|<a class="delete">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
</table> <div class="shade hide"></div>
<div class="add-modal hide">
<form id="add_form" method="POST" action="/app1/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 id="add_submit" 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 src="/static/common.js"></script>
</body>
</html>

app.html

3、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();
}
}
}); });
})

4、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))

【python】-- Django ORM(进阶)的更多相关文章

  1. Django orm进阶查询(聚合、分组、F查询、Q查询)、常见字段、查询优化及事务操作

    Django orm进阶查询(聚合.分组.F查询.Q查询).常见字段.查询优化及事务操作 聚合查询 记住用到关键字aggregate然后还有几个常用的聚合函数就好了 from django.db.mo ...

  2. 9.14.16 Django ORM进阶用法

    2018-9-14 14:26:45 ORM 练习题   : http://www.cnblogs.com/liwenzhou/articles/8337352.html 2018-9-14 21:1 ...

  3. Python - Django - ORM 多对多表结构的三种方式

    多对多的三种方式: ORM 自动创建第三张表 自己创建第三张表, 利用外键分别关联作者和书,关联查询比较麻烦,因为没办法使用 ORM 提供的便利方法 自己创建第三张表,使用 ORM 的 ManyToM ...

  4. Django - ORM - 进阶

    一.多表操作 创建模型 实例:我们来假定下面这些概念,字段和关系 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日,手机号,家庭住址等信息.作者详情模型和作者模型之间是 ...

  5. Python - Django - ORM 操作表

    ORM 的对应关系: 类        --->    数据库表对象     --->    数据库行属性     --->    字段 操作数据库表     --->     ...

  6. Python - Django - ORM 查询方法

    models.py: from django.db import models class Human(models.Model): id = models.AutoField(primary_key ...

  7. python django ORM

    1.在models.py中创创建类 # -*- coding: utf-8 -*- from __future__ import unicode_literals from django.db imp ...

  8. Python - Django - ORM 实例

    准备工作: 首先创建一个名为 Py_Django 的数据库 新建项目,名为 mysite0 创建完成后需要进行几项配置 mysite0/settings.py 下 首先是 html 文件相关 其次是数 ...

  9. Python Django ORM 字段类型、参数、外键操作

    AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 primary ...

  10. Python Django ORM基本增删改查

    工程下的urls.py中增加如下: from cmdb import views as cmdb #要把你要操作的项目import进来 urlpatterns = [ url(r'orm', cmdb ...

随机推荐

  1. 循环List<Object>

    List<Object> infoData=ArrayList<>(); for (int i = 0; i < infoData.size(); i++) { Obje ...

  2. 【MyBatis学习02】走进MyBatis的世界

    mybatis是个持久层的框架,用来执行数据库操作的,无外乎增删改查,上一节对mybatis有了宏观上的了解后,这一篇博客主要通过一个小示例来入门mybatis,先看一下要写的示例需求: 根据用户id ...

  3. mvc5整合Autofac

    本文中将使用 mvc5与webapi2进行对Autofac整合 准备工作: 1.vs2013 or vs2013+ 2.网络良好,nuget正常访问 好了需要的准备工作就这么多. ---------- ...

  4. redis内存分析(转)

    背景 线上经常遇到用户想知道自己 Redis 实例中数据的内存分布情况.为了不影响线上实例的使用,我们一般会采用 bgsave 生成 dump.rdb 文件,再结合 redis-rdb-tools 和 ...

  5. 光栅化规则(Rasterization Rules)

    光栅化规则不是唯一的,只要能满足在扫描线填充过程中,对于一条分割线两边的像素能够被不重复不遗漏地填充即可. 在gdi3d中目前使用的是下面光栅化规则: xLeft_int=ceil(xLeft-0.5 ...

  6. C#取调用堆栈StackTrace

    Environment.StackTrace or System.Diagnostics.StackTrace if you need a more convienient (i.e. not str ...

  7. 红茶一杯话Binder (初始篇)

    1 什么是Binder? 简单地说,Binder是Android平 台上的一种跨进程交互技术.该技术最早并不是由Google公司提出的,它的前身是Be Inc公司开发的OpenBinder,而且在Pa ...

  8. testng入门_单元测试

    1.定义TestNG 的配置文件 <test name="exampletest1">        <classes> <!--1.只执行com.t ...

  9. 183.Wood Cut【hard】

    183.Wood Cut[hard] Given n pieces of wood with length L[i] (integer array). Cut them into small piec ...

  10. shell脚本中处理 路径中中文和空格方法

    OLDIFS=$IFS IFS=$'\n' #存放路径的变量在引用时都使用双引号括起来 "$VAR_PATH" #路径拼接时后续的旧不需要加双引号了"$VAR_PATH& ...