前言:這篇博客主要講下這段時間遇到的小問題。比較雜,我自已當作總結了。
真是尷尬,實習之前我是后台做的比較多,之前花了一個月較系統學了前端html,css,ajax,bootstrap這些,有興趣可以看看我之前寫的前端博客,感覺寫得還可以,對初學者的話。前程明亮-前端系列。學知識嘛,能系統地學習是最好的,出現問題比較容易分析。過去一個月主要是做前端的,so 這篇博客主要寫前端部分。
一、Echarts
echarts是百度開發維護的一個 可視化插件。可視化在系統開發中相當重要,比如現在公司在開發的運維系統DBMS, 監控告警系統,前端都要根據后台傳的數據,利用如echarts, vis.js插件將數據可視化。啥也不多說了,直接看官網吧http://echarts.baidu.com/index.html。第一次看感覺很牛逼! 而且文檔還是中文的!! 即然是中文的,肯定能看懂啦。
在看官網時,有下面的例子:

1 <!DOCTYPE html> 2 <html> 3 <head> 4 <meta charset="utf-8"> 5 <title>ECharts</title> 6 <!-- 引入 echarts.js --> 7 <script src="echarts.js"></script> 8 </head> 9 <body> 10 <!-- 為ECharts准備一個具備大小(寬高)的Dom --> 11 <div id="main" style="width: 600px;height:400px;"></div> 12 <script type="text/javascript"> 13 // 基於准備好的dom,初始化echarts實例 14 var myChart = echarts.init(document.getElementById('main')); 15 16 // 指定圖表的配置項和數據 17 var option = { 18 title: { 19 text: 'ECharts 入門示例' 20 }, 21 tooltip: {}, 22 legend: { 23 data:['銷量'] 24 }, 25 xAxis: { 26 data: ["襯衫","羊毛衫","雪紡衫","褲子","高跟鞋","襪子"] 27 }, 28 yAxis: {}, 29 series: [{ 30 name: '銷量', 31 type: 'bar', 32 data: [5, 20, 36, 10, 10, 20] 33 }] 34 }; 35 36 // 使用剛指定的配置項和數據顯示圖表。 37 myChart.setOption(option); 38 </script> 39 </body> 40 </html>
用瀏覽器打開如下圖:
異步加載
入門示例中的數據是在初始化后setOption
中直接填入的,但是很多時候可能數據需要異步加載后再填入。ECharts
中實現異步數據的更新非常簡單,在圖表初始化后不管任何時候只要通過 jQuery 等工具異步獲取數據后通過 setOption
填入數據和配置項就行。下面是官網的代碼:
1 <!DOCTYPE html>
2 <html lang="en">
3 <head>
4 <meta charset="UTF-8">
5 <title>Title</title>
6 <script src="echarts.js"></script>
7 <script src="../bootstrap-3.3.7-dist/js/jquery-3.1.1.min.js"></script>
8 </head>
9 <body>
10 <!-- 為ECharts准備一個具備大小(寬高)的Dom -->
11 <div id="main" style="width: 600px;height:400px;"></div>
12 <script type="text/javascript">
13
14 var myChart = echarts.init(document.getElementById('main')); 15 // 顯示標題,圖例和空的坐標軸
16 myChart.setOption({ 17 title: { 18 text: '異步數據加載示例'
19 }, 20 tooltip: {}, 21 legend: { 22 data:['銷量'] 23 }, 24 xAxis: { 25 data: [] 26 }, 27 yAxis: {}, 28 series: [{ 29 name: '銷量', 30 type: 'bar', 31 data: [] 32 }] 33 }); 34
35 // 異步加載數據
36 $.get('data_test.json').done(function (data) { 37 // 填入數據
38 myChart.setOption({ 39 xAxis: { 40 data: data.categories 41 }, 42 series: [{ 43 // 根據名字對應到相應的系列
44 name: '銷量', 45 data: data.data 46 }] 47 }); 48 }); 49
50 </script>
51 </body>
52 </html>
當然,我在html文件的同級目錄下,也放下data_test.json文件:上面html代碼36行是通過ajax的GET請求,到data_test.json文件取數據,然后可以通過data.xxx調用json文件的數據。
{ "categories": [ "襯衫", "羊毛衫", "雪紡衫", "褲子", "高跟鞋", "襪子" ], "data": [ 5, 20, 36, 10, 10, 20 ] }
但是我找到HTML文件,用瀏覽器打開,數據加載不出來:
這就懵比了,懷疑人生。看了下瀏覽器的錯誤信息:
WEB開發過程中,很多時候我們都是寫一些簡單的Demo,並不是開發一個完整項目,此時我們常見的操作是:
- 新建文件夾
- 新建需要的文件
- 在Sublime(或其他編輯器)中完成DEMO的編碼
- 雙擊HTML文件,直接在瀏覽器中運行演示
如果此時Demo中有AJAX操作,瀏覽器就會報一個錯:
XMLHttpRequest cannot load file:///Users/iceStone/Documents/Learning/angular/demo/angular-moviecat/movie/view.html. Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
原因很簡單,瀏覽器(Webkit內核)的安全策略決定了file協議訪問的應用無法使用XMLHttpRequest對象,錯誤消息中也很清楚的說明了:
Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https, chrome-extension-resource.
跨域請求僅支持協議:http, data, chrome, chrome-extension, https, chrome-extension-resource
so, 我理解上面的意思是 因為HTML文件里面有ajax方法,你直接右鍵html文件,用瀏覽器打開是無法成功執行ajax方法的。你沒有類似於服務器的東西。
最后我是直接用pycharm IDE打開的本地的echarts5.html,瀏覽器網址如下:
看到沒,本地端口63342,后面還帶了一堆參數,這其實是IDE用我們的本地電腦端口開的一個端口,當作"服務端"。
二、removeClass
移除class樣式,一般我們只需移除一個class, eg:hidden. 但之前有個需求,要移除一個標簽兩個class樣式,怎么做? 查了下jquery的API,果然找到了
要從每個匹配的元素的 class 屬性中移除的一個或多個 class 名稱,多個 class 名稱用空格分隔
三、數據庫導入sql表
一天部門老大,給我發了份sql表,讓我更新下,我也不知咋更新到數據庫,氣氛相當尷尬。
mysql> use bigo_cmdb mysql> source /tmp/instance_meta_info.sql;
說到底還是Linux不夠6唄~_~
四、Django后台如何傳數據給前端JS
這個問題是我用vis.js插件做拓撲圖時遇到的,說到拓撲圖,不禁得吹下牛,真得很屌,明天回公司去截個圖給發上來。多個mysql之間有主從關系,我可以用箭頭表示之間的關系(通過后台數據庫的ID判斷誰指向誰),前端我還自己寫了JS生成拓撲圖。有興趣的可以留言,我可以分享部分代碼。說多了,生成拓撲時我前端的javascript需要后端返回的數據,尼瑪,一般是在html中獲取后台返回的數據,要返回給JS,還真沒遇過:
Django 數據json格式傳輸js
- 把一個 list 或者 dict 傳遞給 js文件,處理后顯示到網頁上, 直接在視圖函數(views.py中的函數)中渲染一個 list 或 dict 的內容,和網頁其它部分一起顯示到網頁上,一次請求一次傳輸。
- views.py中返回的函數中的值要用 json.dumps(xx)處理,參數xx需要字典或者列表。
- 在網頁上要加一個 safe 過濾器。
大致的流程
1、第一步,在view.py渲染
1 # -*- coding: utf-8 -*- 2 from __future__ import unicode_literals 3 import json 4 from django.shortcuts import render 5 def home(request): 6 List = ['列表1', '列表2'] 7 Dict = {'鍵1': '值1', '鍵2': '值2'} 8 return render(request, 'home.html', { 9 'List': json.dumps(List), 10 'Dict': json.dumps(Dict) 11 })
2、第二步,對應需要跳轉的網頁home.html :
1 <script type="text/javascript"> 2 var List = {{ List|safe }};//列表 3 var Dict = {{ Dict|safe }};//字典 4 </script>
ps: 注意分號不要漏了,需要模板語言兩個大括號{{ }};
可參考: http://blog.csdn.net/agly_clarlie/article/details/50551807
五、Bootstrap-select
官網移步: http://silviomoreto.github.io/bootstrap-select/examples/
我對bootstrap-select算是有一定了解。為何? 這就要從模態框說起了,因為之前是在做運維系統,涉及到很多模態框。一個月前剛入職其實都還沒了解模態框這鬼東西~_~ 模態框== 彈出框(我的理解)。先來學習下模態框: 移步bootstrap官網http://v3.bootcss.com/javascript/#modals
這是我之前根據官網博客寫的小demo:
1 <!DOCTYPE html>
2 <html>
3 <head>
4 <meta charset="utf-8">
5 <title>Bootstrap 實例 - 模態框(Modal)插件</title>
6 <link rel="stylesheet" href="../bootstrap-3.3.7-dist/css/bootstrap.min.css">
7
8 </head>
9 <body>
10
11 <h2>創建模態框(Modal)</h2>
12 <!-- 按鈕觸發模態框 -->
13 <button class="btn btn-primary btn-lg" data-toggle="modal" data-target="#myModal">
14 開始演示模態框 15 </button>
16 <!-- 模態框(Modal) -->
17 <div class="modal fade" id="myModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
18 <div class="modal-dialog">
19 <div class="modal-content">
20 <div class="modal-header">
21 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
22 × 23 </button>
24 <h4 class="modal-title" id="myModalLabel">
25 模態框(Modal)標題 26 </h4>
27 </div>
28 <div class="modal-body">
29 在這里添加一些文本 30 </div>
31 <div class="modal-footer">
32 <button type="button" class="btn btn-default" data-dismiss="modal">關閉 33 </button>
34 <button type="button" class="btn btn-primary">
35 提交更改 36 </button>
37 </div>
38 </div><!-- /.modal-content -->
39 </div><!-- /.modal -->
40 </div>
41
42 <script src="../bootstrap-3.3.7-dist/js/jquery-3.1.1.min.js"></script>
43 <script src="../bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
44
45 <!--
46 <script>
47 // 只需要點擊 ESC 鍵,模態窗口即會退出。
48 $(function() { 49 $('#myModal').modal({ 50 keyboard: false
51 }) 52 }); 53 </script>
54 -->
55
56 <script>
57 $(function() { 58 $('#myModal').modal('hide') 59 }); 60 </script>
61
62 <script>
63 $(function() { 64 $('#myModal').on('hide.bs.modal', 65 function() { 66 alert('嘿,我聽說您喜歡模態框...'); 67 }) 68 }); 69 </script>
70
71 </body>
72 </html>
其實bootstrap已經封裝得很牛逼了。模態框說白了就是一個div,但是它有個屬性class="modal",div里面就是modal-content,通俗理解就是模態框的內容,內容又細分為三部分
- modal-header
- modal-body (modal是模態框的重點,一般用來放form表單)
- modal-footer
如果一個界面有多個模態框,你如何知道擊A按鈕就打開A模態框,而不是B模態框?? 很簡單阿
data-target="#myModal"
給button加上data-target屬性,屬性值為需要打開的模態的的ID.
.modal('show')
手動打開模態框。在模態框顯示之前返回到主調函數中 (也就是,在觸發 shown.bs.modal
事件之前)。
$('#myModal').modal('show')
.modal('hide')
手動隱藏模態框。在模態框隱藏之前返回到主調函數中 (也就是,在觸發 hidden.bs.modal
事件之前)。
$('#myModal').modal('hide')
事件
Bootstrap 的模態框類提供了一些事件用於監聽並執行你自己的代碼。
All modal events are fired at the modal itself (i.e. at the <div class="modal">
).
事件類型 | 描述 |
---|---|
show.bs.modal | show 方法調用之后立即觸發該事件。如果是通過點擊某個作為觸發器的元素,則此元素可以通過事件的 relatedTarget 屬性進行訪問。 |
shown.bs.modal | 此事件在模態框已經顯示出來(並且同時在 CSS 過渡效果完成)之后被觸發。如果是通過點擊某個作為觸發器的元素,則此元素可以通過事件的 relatedTarget 屬性進行訪問。 |
hide.bs.modal | hide 方法調用之后立即觸發該事件。 |
hidden.bs.modal | 此事件在模態框被隱藏(並且同時在 CSS 過渡效果完成)之后被觸發。 |
loaded.bs.modal | 從遠端的數據源 加載完數據之后觸發該事件。 |
$('#myModal').on('hidden.bs.modal', function (e) { // do something... })
模態框學習告一段落,具體移步官網。
先回顧下原本的需求:
現在系統有一個mysql實例(包括很多信息IP, sql版本, 運維負責人....),我點擊編輯按紐。比如下圖:我點擊按鈕后彈出模態框如下圖,怎么打開呢?肯定是調用一個onclick方法,JS方法里面再讓模態框show一下。具體代碼現在沒有,明天回公司到SVN找找看。當然,不止編輯按紐,還有新增按鈕,點擊新增按紐也需要打開一個模態框,和下圖一樣布局與樣式,新增的模態框的代碼 復制 編輯模態框的代碼就OK?傻呀,這代碼太多了,所以稍微時智的方法就是新增框與編輯框用同一個模態框modal。
新增框與編輯框有不同,就是新增框form表單里面的input,select標簽是沒有數據的,編輯框是一調用onclick方法,前端發起Ajax方法,后台返回數據,前端再寫JS給編輯框的form表單里面的input,select標簽添加value。
點擊編輯按:

1 function edit_instance_meta(instance_id) { 2 $.ajax({ 3 type: 'GET', 4 url: "/instanceMeta/getInstanceMetaDetail/" + instance_id, 5 data: {}, 6 success: function (callback) { 7 var obj = jQuery.parseJSON(callback)[0]; // type of obj is dict 8 console.log("obj", obj); 9 $("#edit_instance_meta").attr("action", "/instanceMeta/getInstanceMetaDetail/" + instance_id + '/'); 10 11 add_form_message(obj); 12 13 $("input[name='tel_ip']").attr("readonly","readonly"); 14 $("input[name='un_ip']").attr("readonly","readonly"); 15 $("input[name='mob_ip']").attr("readonly","readonly"); 16 $("input[name='in_ip']").attr("readonly","readonly"); 17 $("input[name='man_ip']").attr("readonly","readonly"); 18 $("input[name='login_ip']").attr("readonly","readonly"); 19 20 $('.bs-select').selectpicker('refresh'); 21 // $("textarea#filecontent").empty(); 22 23 $("#edit_instance").modal('show'); 24 25 } 26 }); 27 }
通過JS寫代碼給form表單,一個一個input或者select標簽賦值。這種做法,優點是前后端后離,缺點是代碼量太多,一個form表單你都寫怎么多代碼,多個form表單那還得了。

function add_form_message(obj) { $("select[name='role']").val(obj.role); $("input[name='db_port']").val(obj.db_port); $("select[name='db_type']").val(obj.db_type); $("select[name='is_weihui_machine']").val(obj.is_weihui_machine); $("select[name='backup_status']").val(obj.backup_status); $("select[name='importance_level']").val(obj.importance_level); $("input[name='business_name_desc']").val(obj.business_name_desc); $("input[name='area_num']").val(obj.area_num); $("input[name='room_num']").val(obj.room_num); $("input[name='user_name']").val(obj.user_name); $("input[name='user_passwd']").val(obj.user_passwd); $("select[name='developer']").val(obj.developer_list); $("select[name='operator_des']").val(obj.operator_des_list); $("select[name='developer_des']").val(obj.developer_des_list); $("select[name='rw_role']").val(obj.rw_role); }
清空模態框,注意用bootstrap-select后清空的方試,之前也上網了很久,網上有些方法是直接reset form來清空表單,但是我試了下,只能清空input,textarea標簽,不能清空bootstrap樣式的select標簽!!!
1 // callback function work when modal form close 2 $('#edit_instance').on('hidden.bs.modal', function (e) { 3 4 console.log("hiddden"); 5 6 // can reset input and textarea not select 7 $("#edit_instance_meta").trigger('reset'); 8 9 // can reset select not multiple select 10 var select = $("#edit_instance_meta").find("select").each(function () { 11 this.options.selectedIndex = 0; 12 $(this).selectpicker('refresh'); 13 }); 14 15 // can reset mul select 16 var mul_select = $("#edit_instance_meta").find("select[multiple='multiple']").each(function () { 17 this.options.selectedIndex = -1; 18 $(this).selectpicker('refresh'); 19 }); 20 21 var readonly = $("#edit_instance_meta").find("input[readonly='readonly']").each(function () { 22 $(this).removeAttr("readonly"); 23 }); 24 });
先點擊編輯按紐,打開模態框,關閉,再點擊新增按鈕,猜猜發生啥?天吶! 新增框里面有編輯框“殘留”的數據。為什么呢?因為你關閉編輯模態框的時候沒有清空form表單的數據。
如何清空form表單的數據,input標簽很簡單,令其value=""便可以,但是select標簽就麻煩了。這里的select標簽有使用了流行的bootstrap-select插件。待續……
六、ImportError: No module named runner
使用ansible api setup 收集服務器配置信息。公司是用python2.7 + django1.8版本開發,比較low....
from ansible.runner import Runner 出現ImportError: No module named runner
經一番折騰后發現原來是ansible版本升級后沒有此模塊,降為ansible 1.7.2后正常
新版本以后再折騰
七、雜
1、 Python 的內建函數 locals()
如果你是個喜歡偷懶的程序員並想讓代碼看起來更加簡明,可以利用 Python 的內建函數 locals() 。它返回的字典對所有局部變量的名稱與值進行映射。因此,前面的視圖可以重寫成下面這個樣子:
def current_datetime(request): current_date = datetime.datetime.now() return render_to_response('current_datetime.html', locals())
上面的代碼等於下面的
def current_datetime(request): now = datetime.datetime.now() return render_to_response('current_datetime.html', {'current_date': now})
2、That port is already in use.
我是在Linux下用pycharm開發的,數據庫的API是用本地的8000端口,有時會出現8000端口已被使用。
netstat -ntlp
It will show something like this.
Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:8000 0.0.0.0:* LISTEN 6599/python tcp 0 0 127.0.0.1:27017 0.0.0.0:* LISTEN - tcp 0 0 192.168.124.1:53 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN - tcp6 0 0 :::3306 :::* LISTEN
So now just close the port in which Django/python running already by killing the process associated with it.
kill -9 PID
in my case
kill -9 6599
Now run your Django app.
可參考:https://stackoverflow.com/questions/20239232/error-that-port-is-already-in-use
后期我沒有使用模態框,在老大的建議下改用了layer彈出框,關於layer可以寫的東西太多了,我打開留在下一篇博客寫。下下篇博客會寫表單驗證,表單驗證自己的折騰了很久,學習了很多驗證的插件,都遇到一些問題,最后選用了jquery.validate.js插件。我自己封裝了一個Layer+Jquery.validate.js+Ajax的方法,為部門開發的DBMS和監控項目節省了超多的代碼。

8/12 星期六
應廣大人民群眾要求,特放我做的拓撲圖給各位看看。有些數據不能發出來,各位將就下。