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)

示例:用户管理

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),
]
urls.py
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/')
views.py
<!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>
index.html
<!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>
user_info.html
<!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>
user_detail.html
<!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>
user_edit.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 ===

<!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>
View Code

=== host.html === 

<!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>
View Code

 

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

 

<!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>
app.html

 

添加编辑的两种应用场景
1、模态对话框: 当数据量比较大时不适合用
2、新URL:博客园添加博客

 

 

ORM 反向查询

https://www.cnblogs.com/sss4/p/7070942.html
https://www.cnblogs.com/mosson/p/5806823.html

 

posted @ 2017-12-07 16:27  bobo0609  Views(928)  Comments(0Edit  收藏  举报