一、運維管理系統(基於Flask)回顧
1、權限控制
通過session實現權限控制,session是一個全局字典,當用戶登錄時,可以獲取到用戶的用戶名,通過查找數據庫獲取用戶的權限保存進session中,在每次頁面跳轉時同過查詢session中的權限實現權限管理。
2、base64和md5加密方式的區別
在用戶添加和登錄中使用到了md5加密,md5屬於單向加密,是不可逆的,數據庫密碼保存的是加密後的字符串。同時可以通過加鹽的方式提高密碼的安全性
from hashlib import md5 ... ... password = md5(request.form.get('password')+salt).hexdigest()
在token中使用的就是base64加密算法,base64屬於對稱加密,可以進行解密
import base64,time,random ... ... token = base64.b64encode('%s|%s|%s|%s|%s'% (name,uid,role,str(random.random()),int(time.time()+7200))) ... ... key = base64.b64decode(token)
3、各種前端插件
sweetalert:一款不需要jQuery支持的原生js提示框,顯示更優雅
datatables:一款jQuery表格插件,可以實現分頁,即時搜索和排序
Validform:表單驗證插件,對輸入值進行簡單驗證
highcharts,echaets:數據可視化插件
multiselect:下拉多選插件,使下拉菜更優雅
二、使用echarts繪製中國地圖
實例:獲取網站訪問用戶的全國分佈圖
方法:讀取nginx的訪問日誌,從nginx日誌中通過split()函數獲取訪問用戶的ip地址,將獲取的ip進行統計,獲取一個dict,key是ip地址,value是ip出現次數,使用阿里或百度提供的api接口,通過ip地址獲取到真是的地址並在echarts的中國地圖上顯示。
# 從nginx日誌獲取所有的ip地址 res = {} for line in open('log.log'): tmp = line.split(' ') ip = tmp[0] res[ip] = res.get(ip,0)+1
# 通過baidu的api獲取到真實地址、經緯度,並一起寫入數據庫 token = 'q5mTrTGzCSVq5QmGpI9y18Bo' for key,val in res.items(): url = 'http://api.map.baidu.com/location/ip?ak='+token+'&ip=%s&coor=bd09ll'%(key) r = requests.get(url) geo_data = r.json() if geo_data['status']==0: tmp = (key,geo_data['content']['address_detail']['province'],geo_data['content']['point']['x'],geo_data['content']['point']['y'],val) sql = 'insert into log_map(ip,province,geox,geoy,count) values ("%s","%s","%s","%s",%s)'%tmp cur.execute(sql)
# 回調函數 @app.route('/mapdata') def mapdata(): if not session.get('name'): return redirect("/login") # 獲取所有省份和對應的範圍次數,由於是根據ip進行入庫,多個ip可能屬於同一個省份,故結果需要去重 fields = ['province','count'] data = db.list('log_map',fields) # 相同省份的次數累加,最終結果res = {'北京':40,'上海':50,.....} res = {} for x in data: p_name = x['province'] res[p_name]=res.get(p_name,0)+x['count'] # 將數據拼接爲echart匹配的格式 [{'name':'北京','value':40},{'name':'上海','value':40},...] result = [] for k,v in res.items(): tmp={} # 去掉多餘的後綴 tmp['name'],tmp['value']=k.rstrip('省市回維吾爾壯族自治區'),v result.append(tmp) print result mapdata = {'code':0,'result':result} return json.dumps(mapdata)
三、工單系統
流程:用戶提交工單請求(工單類型,請求內容),發送郵件給管理員,管理員收到郵件後對工單進行處理,併發郵件給工單申請人告知可以執行,申請人執行後再次發送郵件給管理員報告執行完畢,管理員根據執行的結果,對工單進行處理(成功或失敗),並對工單進行處理反饋。
工單申請
@app.route("/jobadd/",methods=['GET','POST']) @login_request.login_request def jobadd(): name = session.get('name') id = session.get('id') if request.method == 'GET': return render_template('/job/jobadd.html',info = session,role = session.get('role')) else: # 獲取申請類型和請求內容 data = dict((k,v[0]) for k,v in dict(request.form).items()) # 添加申請人 data['apply_persion'] = name # 請求內容不能爲空,將數據保存到數據庫 if not data['apply_desc']: return json.dumps({'code':1,'errmsg':'job description can not be null'}) conditions = [ "%s='%s'" % (k,v) for k,v in data.items()] db.add('ops_jobs',conditions) # # 獲取申請人信息 # user = db.list('users',fields_user,id) # # 從用戶列表獲取郵箱賬號和密碼(暫時沒有) # email,passwd = user['email'],user['password'] # # 發送郵件(需要發件人賬號密碼,密碼,收件人,正文) # myMail.mymail(email,passwd,localemail,data) return json.dumps({'code':0,'result':'apply job success'})
工單處理
# 修改工單狀態 ''' {'0':'未處理','1':'處理中','2':'完成','3':'失敗'} ''' @app.route('/update_status/',methods=['POST']) @login_request.login_request def update_status(): data = dict((k,v[0]) for k,v in dict(request.form).items()) res = {} if data['status'] == '1': # 當工單爲未處理狀態時,第一次對工單處理,只添加處理人信息 data['deal_persion'] = session.get('name') else: # 第二次處理則添加處理結束的時間信息 data['deal_time'] = time.strftime(ISOTIMEFORMAT,time.localtime()) conditions = [ "%s='%s'" % (k,v) for k,v in data.items()] db.update('ops_jobs',conditions,data['id']) return json.dumps({'code':0,'result':'execute completed!'})
顯示工單時,只需要根據工單的狀態‘0’,‘1’爲工單申請列表,‘2’,‘3’則爲工單的歷史列表
工單申請列表需通過申請時間倒序排序,同理,歷史列表通過處理結束時間倒序排序,讓列表一目瞭然
在工單處理時,可以根據當前的狀態,對操作進行隱藏,減少很多不必要的麻煩
{% if job.status == 0 %} <button data-id='`job`.`id`' class='btn btn-info exec'>處理</button> <button data-id='`job`.`id`' disabled='disabled' class='btn btn-success complete'>完成</button> {% elif job.status == 1 %} <button data-id='`job`.`id`' disabled='disabled' class='btn btn-info exec'>處理中</button> <button data-id='`job`.`id`' class='btn btn-success complete'>完成</button> {% endif %}
效果圖
四、模擬面試總結
非常感謝小飛同學的記錄,總結見附件。