• openstack页面自己定义插件使用具体解释(django、ajax、post)(zTree为例)


    感谢朋友支持本博客,欢迎共同探讨交流。因为能力和时间有限,错误之处在所难免,欢迎指正!

    如有转载。请保留源作者博客信息。


    Better Me的博客blog.csdn.net/tantexian

    如需交流,欢迎大家博客留言。


    1、鉴于国内java开发者比較多。java web方面的技术比較成熟。所以用python django(openstack)框架和java的strurs做个类比,让大家可以更直观的理解、更快的进入到开发中:


    附图大致对照下,详细细节,自行查找相关资料:

    2、接下来正式開始解说。怎样在openstack中使用自己定义插件,本文以Jquery zTree树形插件为例。
    第一步封装url地址。请求数据,在urls中自己定义url:
    为了方便兴许大家复制代码,也顺带附上源码
    urlpatterns = patterns('',
        url(r'^$', views.IndexView.as_view(), name='index'),
        url(r'^(?

    P<tenant_id>[^/]+)/update/$',views.UpdateIsolationView.as_view(), name='update'),

        url(r'^(?P<tenant_id>[^/]+)/tree/$',views.TreeView.as_view(), name='tree'),
        url(r'^(?P<tenant_id>[^/]+)/get_tree_data/$',views.JSONGetView.as_view(), name='get_tree_data'),
        url(r'^(?P<tenant_id>[^/]+)/set_tree$',views.JSONSetView.as_view(), name='set_tree'),
    )


    3、依据url规则匹配到相应的views的JSONGetView类:

    from django.views import generic
    from django.http import HttpResponse # noqa
    import json
    class JSONGetView(generic.View):
        def get(self, request, *args, **kwargs): #定义get方法
            tenant_id = self.kwargs["tenant_id"] #从url中截取參数值tenant_id
            aggregates = []
            try:
                aggregates = api.nova.aggregate_details_list(self.request)
                api.nova.isolatation_tree_list(self.request, tenant_id)
            except Exception:
                exceptions.handle(request,
                                  _('Unable to retrieve host aggregates list.'))
            aggregates.sort(key=lambda aggregate: aggregate.name.lower())
    #调用底层api 构造 zTree的数据
            tree_list = []
            for ag in aggregates:
                tree_data = {}
                tree_data['id'] = ag.availability_zone
                tree_data['name'] = ag.availability_zone
                tree_data['pId'] = 'NULL'
                tree_data['open'] = 'true'
                if tree_data not in tree_list:
                    tree_list.append(tree_data)
                tree_data = {}
                tree_data['id'] = ag.name
                tree_data['name'] = ag.name
                tree_data['pId'] = ag.availability_zone
                tree_data['open'] = 'true'
                if tree_data not in tree_list:
                    tree_list.append(tree_data)
                for hostname in ag.hosts:
                    tree_data = {}
                    tree_data['id'] = hostname
                    tree_data['name'] = hostname
                    tree_data['pId'] = ag.name
                    tree_data['open'] = 'true'
                    if tree_data not in tree_list:
                        tree_list.append(tree_data)
            result = json.dumps(tree_list) #此处将python对象转换成json对象
            print (result)
            return HttpResponse(result,content_type="application/json")

    4、到此获取数据的url完毕,測试下url(浏览器直接訪问):
    得到数据:
    [{
     "open": "true",
     "pId": "NULL",
     "id": "zone1",
     "name": "zone1"
    },
    {
     "open": "true",
     "pId": "zone1",
     "id": "ag1",
     "name": "ag1"
    },
    {
     "open": "true",
     "pId": "ag1",
     "id": "node32",
     "name": "node32"
    },
    {
     "open": "true",
     "pId": "ag1",
     "id": "node31",
     "name": "node31"
    },
    {
     "open": "true",
     "pId": "zone1",
     "id": "ag2",
     "name": "ag2"
    },
    {
     "open": "true",
     "pId": "ag2",
     "id": "node33",
     "name": "node33"
    },
    {
     "open": "true",
     "pId": "NULL",
     "id": "zone2",
     "name": "zone2"
    },
    {
     "open": "true",
     "pId": "zone2",
     "id": "ag3",
     "name": "ag3"
    },
    {
     "open": "true",
     "pId": "ag3",
     "id": "node35",
     "name": "node35"
    },
    {
     "open": "true",
     "pId": "ag3",
     "id": "node34",
     "name": "node34"
    }]
    url能正确获取数据。測试通过。


    5、用ajax在html页面中请求该url获取数据:
    先附上页面模板代码:

    当中javascript要写在标签{% block modal-body %}中才干失效。详细的zTree的js导入本文使用了为压缩的方式。直接导入。



    {# add by ttx 2014-9-25#}
      <link rel="stylesheet" href="{{ STATIC_URL }}dashboard/js/zTree/css/demo.css" type="text/css">
     <link rel="stylesheet" href="{{ STATIC_URL }}dashboard/js/zTree/css/zTreeStyle/zTreeStyle.css" type="text/css">
     <script type="text/javascript" src="{{ STATIC_URL }}dashboard/js/zTree/js/jquery.ztree.core-3.5.js"></script>
     <script type="text/javascript" src="{{ STATIC_URL }}dashboard/js/zTree/js/jquery.ztree.excheck-3.5.js"></script>
    zTree插件路径:

    具体解释ajax请求:
    var url = '/dashboard/admin/isolations/{{ tenant_id }}/get_tree_data'; #此处为ajax的url地址,与步骤4中浏览器訪问一致
     $.ajax({ #当中$代表Jquery插件,ajax为Jquery插件的方法
                 type: "get", #type主要有get、post。当中get用于获取数据。是幂等操作、post用于跟新数据
                 async: false, #false代码同步刷新,true代表异步刷新。本演示样例须要等到数据返回再进行tree的渲染,因此须要同步
                 url: url, #请求的url地址
                 dataType: "json", #数据返回类型为json
                  success: function (data) { #ajax请求成功之后得到数据data。运行success:后面function里面代码
                               json = JSON.stringify(data);
                               host_tree_data = JSON.parse(json)
                    }
    });
    很多其它ajax具体使用解说请自行參考相关资料。


    兴许就是具体的zTree依据得到的数据host_tree_data 。生成zone、aggregate、host的节点树。附上简单代码。不具体解释:
    {% extends "horizon/common/_modal_form.html" %}
    {% load i18n %}
    {% load url from future %}
    {% block form_id %}create_image_form{% endblock %}
    {% block form_action %}{% url 'horizon:admin:images:create' %}{% endblock %}
    {% block form_attrs %}enctype="multipart/form-data"{% endblock %}
    {% block modal-header %}{% trans "Isolatation tree" %}{% endblock %}
    {% block modal-body %}
     <SCRIPT type="text/javascript">
      <!--
      var setting = {
       view: {
        selectedMulti: false
       },
       check: {
        enable: true
       },
       data: {
        simpleData: {
         enable: true
        }
       },
       callback: {
        beforeCheck: beforeCheck,
        onCheck: onCheck
       }
      };
      var code, log, className = "dark";
      function beforeCheck(treeId, treeNode) {
       className = (className === "dark" ?

    "":"dark");

       showLog("[ "+getTime()+" beforeCheck ]&nbsp;&nbsp;&nbsp;&nbsp;" + treeNode.name );
       return (treeNode.doCheck !== false);
      }
      function onCheck(e, treeId, treeNode) {
       showLog("[ "+getTime()+" onCheck ]&nbsp;&nbsp;&nbsp;&nbsp;" + treeNode.name );
                getAllChangeNodes()
      }
            function getAllChangeNodes() {
       var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
                var nodes = treeObj.getChangeCheckedNodes();
                $('#mytest').html(JSON.stringify(nodes));
                var url = '/dashboard/admin/isolations/{{ tenant_id }}/set_tree';
                var data={};
                data["jsonTree"] = JSON.stringify(nodes);
                jQuery.ajax({
                    type:"POST",
                    url : url,
                    data:data,
                    dataType : "json",
                    beforeSend: function(xhr, settings){
                          var csrftoken = $.cookie('csrftoken');
                          xhr.setRequestHeader("X-CSRFToken", csrftoken);
                      },
                    success : function(data) {
                    }
                });
      }
      function showLog(str) {
       if (!log) log = $("#log");
       log.append("<li class='"+className+"'>"+str+"</li>");
       if(log.children("li").length > 6) {
        log.get(0).removeChild(log.children("li")[0]);
       }
      }
      function getTime() {
       var now= new Date(),
       h=now.getHours(),
       m=now.getMinutes(),
       s=now.getSeconds(),
       ms=now.getMilliseconds();
       return (h+":"+m+":"+s+ " " +ms);
      }
      function checkNode(e) {
       var zTree = $.fn.zTree.getZTreeObj("treeDemo"),
       type = e.data.type,
       nodes = zTree.getSelectedNodes();
       if (type.indexOf("All")<0 && nodes.length == 0) {
        alert("请先选择一个节点");
       }
       if (type == "checkAllTrue") {
        zTree.checkAllNodes(true);
       } else if (type == "checkAllFalse") {
        zTree.checkAllNodes(false);
       } else {
        var callbackFlag = $("#callbackTrigger").attr("checked");
        for (var i=0, l=nodes.length; i<l; i++) {
         if (type == "checkTrue") {
          zTree.checkNode(nodes[i], true, false, callbackFlag);
         } else if (type == "checkFalse") {
          zTree.checkNode(nodes[i], false, false, callbackFlag);
         } else if (type == "toggle") {
          zTree.checkNode(nodes[i], null, false, callbackFlag);
         }else if (type == "checkTruePS") {
          zTree.checkNode(nodes[i], true, true, callbackFlag);
         } else if (type == "checkFalsePS") {
          zTree.checkNode(nodes[i], false, true, callbackFlag);
         } else if (type == "togglePS") {
          zTree.checkNode(nodes[i], null, true, callbackFlag);
         }
        }
       }
      }
      function setAutoTrigger(e) {
       var zTree = $.fn.zTree.getZTreeObj("treeDemo");
       zTree.setting.check.autoCheckTrigger = $("#autoCallbackTrigger").attr("checked");
       $("#autoCheckTriggerValue").html(zTree.setting.check.autoCheckTrigger ? "true" : "false");
      }
      $(document).ready(function(){
                var url = '/dashboard/admin/isolations/{{ tenant_id }}/get_tree_data';
                $.ajax({
                           type: "get",
                           async: false,
                           url: url,
                           dataType: "json",
                           success: function (data) {
                               json = JSON.stringify(data);
                               host_tree_data = JSON.parse(json)
                           }
                       });
                var zNodes =[
                                { id:1, pId:0, name:"1", open:true},
                                { id:11, pId:1, name:"1-1"},
                                { id:12, pId:1, name:"1-2"},
                                { id:111, pId:11, name:"1-1-1","checked":"true"},
                                { id:112, pId:11, name:"1-1-2"},
                            ];
       $.fn.zTree.init($("#treeDemo"), setting, host_tree_data);
       $("#checkTrue").bind("click", {type:"checkTrue"}, checkNode);
       $("#checkFalse").bind("click", {type:"checkFalse"}, checkNode);
       $("#toggle").bind("click", {type:"toggle"}, checkNode);
       $("#checkTruePS").bind("click", {type:"checkTruePS"}, checkNode);
       $("#checkFalsePS").bind("click", {type:"checkFalsePS"}, checkNode);
       $("#togglePS").bind("click", {type:"togglePS"}, checkNode);
       $("#checkAllTrue").bind("click", {type:"checkAllTrue"}, checkNode);
       $("#checkAllFalse").bind("click", {type:"checkAllFalse"}, checkNode);
       $("#autoCallbackTrigger").bind("change", {}, setAutoTrigger);
      });
      //-->
     </SCRIPT>
    <h1>用 zTree 方法 勾选 checkbox</h1>
    <h6>[ 文件路径: excheck/checkbox_fun.html ]</h6>
    <div class="content_wrap">
     <div class="zTreeDemoBackground left">
      <ul id="treeDemo" class="ztree"></ul>
     </div>
    </div>
     <div>
      <ul class="info">
                <div id="mytest">11111111111111111111111111111111111111111111</div>
       <li class="title"><h2>1、beforeCheck / onCheck 事件回调函数控制</h2>
        <ul class="list">
        <li>利用 beforeCheck / onCheck 事件回调函数 能够控制是否同意 更改 节点勾选状态,这里简单演示怎样监控此事件</li>
        <li><p>这里还演示了 checkNode / checkAllNodes 方法触发 beforeCheck / onCheck 事件回调函数的情况。试试看:<br/>
         &nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" id="autoCallbackTrigger" /> setting.check.autoCheckTrigger: <span id="autoCheckTriggerValue">false</span><br/>
         &nbsp;&nbsp;&nbsp;&nbsp;<input type="checkbox" id="callbackTrigger" checked /> 运行勾选方法是否触发 callback <br/>
         &nbsp;&nbsp;&nbsp;&nbsp;单节点--[ <a id="checkTrue" href="#" title="不想勾选我就不勾选你..." onclick="return false;">勾选</a> ]
         &nbsp;&nbsp;&nbsp;&nbsp;[ <a id="checkFalse" href="#" title="不想取消勾选我就不取消你..." onclick="return false;">取消勾选</a> ]
         &nbsp;&nbsp;&nbsp;&nbsp;[ <a id="toggle" href="#" title="你想如何?..." onclick="return false;">勾选 切换</a> ]<br/>
         &nbsp;&nbsp;&nbsp;&nbsp;单节点 ( 影响父子 )--[ <a id="checkTruePS" href="#" title="不想勾选我就不勾选你..." onclick="return false;">勾选</a> ]
         &nbsp;&nbsp;&nbsp;&nbsp;[ <a id="checkFalsePS" href="#" title="不想取消勾选我就不取消你..." onclick="return false;">取消勾选</a> ]
         &nbsp;&nbsp;&nbsp;&nbsp;[ <a id="togglePS" href="#" title="你想如何?..." onclick="return false;">勾选 切换</a> ]<br/>
         &nbsp;&nbsp;&nbsp;&nbsp;所有节点--[ <a id="checkAllTrue" href="#" title="无论你有多NB,统统都要听我的!

    " onclick="return false;">勾选</a> ]

         &nbsp;&nbsp;&nbsp;&nbsp;[ <a id="checkAllFalse" href="#" title="无论你有多NB,统统都要听我的!

    " onclick="return false;">取消勾选</a> ]</p>

        </li>
        <li><p><span class="highlight_red">使用 zTreeObj.checkNode / checkAllNodes 方法,具体请參见 API 文档中的相关内容</span><br/>
         beforeCheck / onCheck log:<br/>
         <ul id="log" class="log" style="height:130px;"></ul></p>
        </li>
        </ul>
       </li>
       <li class="title"><h2>2、setting 配置信息说明</h2>
        <ul class="list">
        <li>同 "checkbox 勾选操作" 中的说明</li>
        </ul>
       </li>
       <li class="title"><h2>3、treeNode 节点数据说明</h2>
        <ul class="list">
        <li>同 "checkbox 勾选操作" 中的说明</li>
        </ul>
       </li>
      </ul>
     </div>
    {% endblock %}
    {% block modal-footer %}
      <input class="btn btn-primary pull-right" type="submit" value="{% trans "Save" %}" />
      <a href="{% url 'horizon:admin:images:index' %}" class="btn secondary cancel close">{% trans "Cancel" %}</a>
    {% endblock %}
    跟多zTree使用,请自行參考zTree官网:www.ztree.me/

    页面终于展示:
    此处的zTree页面比較丑。能够改动css样式,调整,附上bootstrap风格的树形插件样式。http://www.js-css.cn/jscode/nav/nav23/

    到此通过ajax获取数据到页面展示解说完成。

    6、讲完ajax从后台获取数据到前台接下来解说,怎样通过ajax,把页面的数据传递给后台处理:
    附上代码:
    function getAllChangeNodes() {
       var treeObj = $.fn.zTree.getZTreeObj("treeDemo");
                var nodes = treeObj.getChangeCheckedNodes();
                $('#mytest').html(JSON.stringify(nodes)); #JSON.stringify(nodes)将js对象nodes,转化为json对象
                var url = '/dashboard/admin/isolations/{{ tenant_id }}/set_tree';
                var data={}; #url中传递的数据,相当于$url?

    jsonTree=JSON.stringify(nodes)

                data["jsonTree"] = JSON.stringify(nodes);
                jQuery.ajax({
                    type:"POST", #ajax类型。post进来进行更新
                    url : url,
                    data:data,
                    dataType : "json",
                    beforeSend: function(xhr, settings){ #此处的beforeSend用来解决ajax在django中报csrftoken错误
                          var csrftoken = $.cookie('csrftoken');
                          xhr.setRequestHeader("X-CSRFToken", csrftoken);
                      },
                    success : function(data) { #ajax请求成功之后运行
                    }
                });
      }

    依据上述url = '/dashboard/admin/isolations/{{ tenant_id }}/set_tree';到urls.py中找相应匹配的url:
    urlpatterns = patterns('',
        url(r'^$', views.IndexView.as_view(), name='index'),
        url(r'^(?P<tenant_id>[^/]+)/update/$',views.UpdateIsolationView.as_view(), name='update'),
        url(r'^(?

    P<tenant_id>[^/]+)/tree/$',views.TreeView.as_view(), name='tree'),

        url(r'^(?P<tenant_id>[^/]+)/get_tree_data/$',views.JSONGetView.as_view(), name='get_tree_data'),
        url(r'^(?P<tenant_id>[^/]+)/set_tree$',views.JSONSetView.as_view(), name='set_tree'),
    )



    依据url匹配规则,跟进到JSONSetView:
    class JSONSetView(generic.View):
        def post(self, request, *args, **kwargs): #由于ajax的请求类型为post因此实现post函数,否则会报错
            tenant_id = self.kwargs["tenant_id"] #从URL中获取tenant_id
            json_tree = request.POST.get("jsonTree") #从ajax发过来的请求中获取jsonTree json数据
            tree_change_nodes = json.loads(json_tree) #将页面传递的json数据,转换为python对象。详细转换规则自行參考
    #此处依据前端传送的数据,调用api传递给后端处理
            api.nova.isolatation_add_tree(request, tenant_id, tree_change_nodes) 
            return HttpResponse(tree_change_nodes,content_type="application/json")

    解说完成!

  • 相关阅读:
    GIT基础详解
    JS进阶解析
    JS基础解析
    CSS布局模型解析
    02.CentOS Linux 7.7 系统配置文档
    docker 创建bridge网络和修改默认网段
    selenium浏览器自动化测试工具 进阶使用
    前端导出Excel和打印介绍
    stm32使用gmtime()转换timestamp为日期,出的结果是乱的,不符合预期。改为localtime正常输出
    .net core api action 不能用作 httpget注释的参数名
  • 原文地址:https://www.cnblogs.com/yjbjingcha/p/6903618.html
Copyright © 2020-2023  润新知