zoukankan      html  css  js  c++  java
  • 【python】-- Django ORM(进阶)

    Django ORM(进阶)

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

    一、一对多:models.ForeignKey()

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

     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()函数的主要参数
    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')
    正向、反向查询、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:

    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 ]
    app中urls.py的路由规则

    2、templates:

    为了演示方便,没有对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              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>
    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()

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

     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,              # 默认创建第三张表时,数据库中表的名称
    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自动创建关系表的间接操作方式

     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=2、id=3、id=4(主机)
    12 obj.host.add(2, 3, 4)
    13 # 在关系表中添加Application、host(单个服务应用、多个主机列表形式)对应关系 对应条件:Application表中id=1(服务应用),# host表中id=1、id=2、id=3、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=2、id=4(主机)
    19 obj.host.remove(2, 4)
    20 # 在关系表中移除Application、host(单个服务应用、多个主机列表形式)对应关系 对应条件:Application表中id=1(服务应用),# host表中id=1、id=2、id=3、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=1、id=2、id=3(主机)
    28 obj.host.set([1, 2, 3])
    29 
    30 # 所相关的主机对象QuerySet
    31 obj.host.all()
    关系表的间接操作方式

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

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

    1、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 ]
    app中urls.py的路由规则

    2、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>
    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))
    
  • 相关阅读:
    实例之内存体系结构(1)--- 共享池(Share pool)
    体系结构 --- 实例和数据库
    分页查询与TOP-N特性
    MERGE 和 WITH语法
    外部表
    SQL语句(9)--- 同义词
    SQL语句(8)--- 索引
    SQL语句(7)--- 视图
    SQL语句(6)--- 约束
    死锁的产生与解决
  • 原文地址:https://www.cnblogs.com/Keep-Ambition/p/8446450.html
Copyright © 2011-2022 走看看