摘要:本文將為大家帶來基於Flask框架和JQuery實現管理平台網站的開發功能。
【寫在前面】
你要開發網站? 嗯。。
會Flask嗎? 什么東西,沒聽過。。。
會JQuery嗎? 是python的庫嗎 ?
那你會什么? 我會F12打開網站
好吧,那我們來寫個簡單的表格管理平台。
基於Flask框架和JQuery實現管理平台網站的開發功能,我代碼編寫用了2天的時間 ,從零開始寫;又對具體實現流程,自己斷斷續續地整理總結了近半個月。從自我感覺來說,整個過程和結果的實現都讓我很滿意。
【效果如下】
【第一步】了解Flask框架
1、了解python 主流的web框架
(1)Django:簡單來說就是重武器,是最全能的開發框架,你想要的功能它都有;但是比較繁重,適合企業級的web開發;
(2)Flask:屬於web開發微框架,小巧靈活,相關的第三方庫豐富,適合開發小型web;
(3)Tornado:天生異步,性能強悍,但是框架提供的功能少,需要開發者自己實現;
因此,本文代碼實現主要是基於Flask實現的。
2、了解Flask框架
(1)HelloWorld實現:
幾乎所有的編程都是基於“hello world”實現的,因此也大致講下helloworld涉及的內容。
from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return "Hello world!" if __name__ == '__main__': app.run()
先聲明一個Flask框架的對象,然后定義路由'/',即URL地址為 http://127.0.0.1:5000/;如果定義路徑為‘/new’,那對應的訪問地址需要改為http://127.0.0.1:5000/new。另外,@app.route是個裝飾器。
(2)如何實現具體IP地址或者端口的訪問呢?
app.run(debug=True,host="x.x.x.x",port="1234")
通過對app.run()方法的參數定義,分別實現了調試功能,訪問URL變更為 http://x.x.x.x:1234
這里調試功能還是很好用的,不但可以幫助開發者重新加載網頁,而且會打印詳細的錯誤信息,協助定位。
(3)如何在web上顯示自己特定的html模板
from flask import Flask,render_template app = Flask(__name__) @app.route('/') def hello_world(): return render_template('test.html') if __name__ == '__main__': app.run()
只需要導入render_template庫,並且在函數返回時改成對應的方法即可。
不過 這 里要 注意,test.html必須保存在工程目錄與下template文件下,否則會報錯。(這是因為render_template方法定義時默認寫了template路徑 )
【第二步】了解Sqlite3數據庫
web數據交互離不開后台數據庫的管理,本章節重點解釋python自帶的sqlite3數據庫。相比較於其他“正規”的數據庫,如mongo、solr、MySQL等,sqlite3相當簡單,屬於輕量級的數據庫。
1、sqlite3數據庫的安裝和創建
用pip命令可以下載安裝sqlite3數據庫
創建數據庫:
con = sqlite3.connect('material.db')
如果有數據庫material.db,則進行連接數據庫的操作;如果沒有此數據庫,則先創建數據庫再進行連接;
2、創建數據表
label = ['ID','網絡IP','地址','責任人','聯系方式'] content = ['1','10.10.10.10','杭州濱江','鵬哥','123456'] def create(): sql = 'create table {0} ({1},{2},{3},{4},{5})'.format(tablename,label[0],label[1],label[2],label[3],label[4]) result = cur.execute(sql) con.commit() return True if result else False
簡單描述為:create table 表名 (各字段名1,各字段名2……)
當前對數據表的字段未進行輸入類型及長度的限制,比如需要規則ID為必填項,並且為整形,長度在10個字節內,則需要修改為
sql = 'create table matrial_table ("ID" int[10] primary key not null )'
同理,其他字段也可以相同的方式進行類型、長度的限制。
注意:在執行cur.execute()后,要記得con.commit()進行數據庫提交,否則數據並不會真正寫入數據庫中。
3、插入數據
def insert(): sql = 'insert into {0} ({1},{2},{3},{4},{5}) values({6},"{7}","{8}","{9}","{10}")'.format(tablename,label[0],label[1], label[2],label[3],label[4],content[0],content[1],content[2],content[3],content[4]) result = cur.execute(sql) con.commit() return True if result else False
簡單描述為:insert into 表名 (各字段名1,各字段名2……) values(數值1,數值2……)
這 里要注意,”{7}“ 是有加雙引號的,為什么呢?因為”{7}“對應的是網絡IP,是個字符串,因此需要加 雙引號,否則會報錯。
4、查詢數據
def query(): sql = 'select * from {0}'.format(tablename) result = cur.execute(sql) return list(result)
簡單描述為:select XX,XX from 表名 where 字段名1="數值1"
5、更新數據:update 表名 set 字段名1=”數值1“ where 字段名2="數值2"
6、刪除某條數據:delete from 表名 where 字段名1="數值1"
【補充】
如果生成了db數據庫,如何查看呢?可以下載一個SQLite Expert,打開后就可以很直觀地進行數據庫查看,並且可以通過圖形化按鈕進行 數據表的增刪改查。
【第三步】了解html
1、Flask框架方法編寫
前面已經講過 Flask如何調用html模板,因此我們直接展示上圖對應的flask框架方法的代碼
# coding=utf-8 # @Auther : "鵬哥賊優秀" # @Date : 2019/9/23 # @Software : PyCharm from flask import Flask,render_template import sqlite3 app = Flask(__name__) con = sqlite3.connect('material.db',check_same_thread=False) @app.route('/') def Material_Mangement(): # 獲取數據庫material_table表的內容 cur = con.cursor() sql = 'select * from {0}'.format("material_table") cur.execute(sql) content = cur.fetchall() # 獲取數據庫表的表頭 labels = [tuple[0] for tuple in cur.description] return render_template('test.html',content=content,labels=labels) if __name__ == '__main__': app.run(debug=True)
動態路由、sqlite3數據庫操作、調試模式的設置,這些知識請參考之前的博客。但有2個知識點,我想再提下:
(1)如果在數據庫連接時,不添加check_same_thread=False參數,則
數據庫連接會報錯:sqlite3.ProgrammingError: SQLite objects created in a thread can only be used in that same thread. The object was created in thread id XX。
這是因為sqlite3數據庫被多線程訪問導致沖突,因此這里要注意下。
(2)獲取數據庫表頭:labels = [tuple[0] for tuple in cur.description]
2、Html文件(僅展示表格內容)
<!doctype html> <html> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> <title>物料管理平台</title> </head> <body> <div> <div class="col-md-6 col-sm-12 col-xs-12"> <div class="panel panel-default"> <div> <h3>表格管理平台</h3> </div> <div> <div> <table class="table table-striped table-bordered table-hover"> <thead> <tr> {% for i in labels %} <td>{{ i }}</td> {% endfor %} </tr> </thead> <tbody> {% for i in content %} <tr> {% for j in i %} <td>{{ j }}</td> {% endfor %} </tr> {% endfor %} </tbody> </table> </div> </div> </div> </div> </div> <!-- Optional JavaScript --> <!-- jQuery first, then Popper.js, then Bootstrap JS --> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script> </body> </html>
對應的效果是這樣的:
因為一開始接觸flask時,我只調試過html,但是根本沒具體接觸過html怎么寫。因此上述這段代碼是參考於大神的代碼(https://blog.csdn.net/a19990412/article/details/84955802)。
熟悉這段代碼后,我覺得有幾塊內容是和我要實現的代碼有關的。
(1)title 標題修改
(2)表格的長寬大小:<div class="col-md-6 col-sm-12 col-xs-12"> 。 col-xs-*和col-sm-* 和col-md-*(col-xs表示超小屏幕,col-md-中等屏幕,col-sm-小屏幕)主要是用來適應不同屏幕的表格展示。因此需要自適應調整對應的數值。
(3)設置表格的ID:<table class="table table-striped table-bordered table-hover",id="test">。這里其實不設置id也是可以的,但是后續我要對表格進行編輯時,加上id會方便我定位表格,方法是:tab = document.getElementById("test")
3、Html文件(添加編輯、提交按鈕)
根據上述要修改的點,我重新修改了html內容,新的html代碼如下:
<!doctype html> <html> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> <title>表格管理平台</title> </head> <body> <div> <div class="col-md-12 col-sm-12 col-xs-12"> <div class="panel panel-default"> <div> <h3>表格管理平台</h3> </div> <div> <div> <table class="table table-striped table-bordered table-hover"> <thead> <tr> {% for i in labels %} <td>{{ i }}</td> {% endfor %} </tr> </thead> <tbody> {% for i in content %} <tr> {% for j in i %} <td>{{ j }}</td> {% endfor %} <td><input type="button" value="編輯"></td> <td><input type="submit" value="提交"></td> </tr> {% endfor %} </tbody> </table> </div> </div> </div> </div> </div> <!-- Optional JavaScript --> <!-- jQuery first, then Popper.js, then Bootstrap JS --> <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js" integrity="sha384-ZMP7rVo3mIykV+2+9J3UJ46jBk0WLaUAdn689aCwoqbBJiSnjAK/l8WvCWPIPm49" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js" integrity="sha384-ChfqqxuZUCnJSK3+MXmPNIyE6ZbWh2IMqE241rYiqJxyMiZ6OW/JmZQ5stwEULTy" crossorigin="anonymous"></script> <script> (function(){ $('input[type="button"]').on('click', function(){ var $this = $(this), edit_status = $this.attr('edit_status'), status_value = edit_status && 1 == edit_status ? 0 : 1, $td_arr = $this.parent().prevAll('td'); $this.val(1 == status_value ? '完成' : '編輯').attr('edit_status', status_value); $.each($td_arr, function(){ var $td = $(this); if(1 == status_value) { $td.html('<input type="text" value="'+$td.html()+'">'); } else if(0 == status_value){ $td.html($td.find('input[type=text]').val()); } }); }); })(); </script> </body> </html>
相比於第 2步時的html文件,這次我主要添加了2塊內容:
(1)添加編輯、提交按鈕:
<td><input type="button" value="編輯"></td> <td><input type="submit" value="提交"></td>
將這兩行代碼放在表格每行最后,就會生成相應的按鈕
(2)編輯功能的實現:
編輯按鈕對應的function是基於JQuery寫的,
當然這 段代碼我也是參考另一位大神的(https://blog.csdn.net/luo201227/article/details/50559988),因為當前我對JQuery完全一無所知。
但是在熟悉代碼后,我根據自己對代碼的理解進行了注釋。
<script> (function(){ <!--定義屬於是 button的按鈕在點擊后,產生下面的function功能--> $('input[type="button"]').on('click', function(){ <!--獲取當前事件,並進行當前按鈕的狀態,如果是編輯狀態,就進行將每個單元格設置成可輸入狀態--> var $this = $(this), edit_status = $this.attr('edit_status'), status_value = edit_status && 1 == edit_status ? 0 : 1, $td_arr = $this.parent().prevAll('td'); $this.val(1 == status_value ? '完成' : '編輯').attr('edit_status', status_value); <!--如果單元格是可編輯狀態,獲取每列元素的值,並在最后html表格上進行展示--> $.each($td_arr, function(){ var $td = $(this); if(1 == status_value) { $td.html('<input type="text" value="'+$td.html()+'">'); <!--如果按鈕狀態是完成狀態,直接展示單元內的值--> } else if(0 == status_value){ $td.html($td.find('input[type=text]').val()); } }); }); })(); </script>
細心的同學會發現,我在點擊”提交“按鈕時,什么都沒 發生。是的,”提交“功能,我將在下一個章節中進行介紹。
【第四步】了解JQuery
1、提交功能的實現,對我來說,最難的是html對前台數據的傳輸。因此,我就參考着編輯功能,自己一 點點寫。以下是示例代碼:
(1)HTML文件編寫前台界面提交功能
<script> (function(){ <!--定義屬性是submit的按鈕在點擊后,產生下面的function功能--> $('input[type="submit"]').on('click', function(){ <!--獲取當前行的id --> var td = event.srcElement.parentElement; var rownum = td.parentElement.rowIndex; <!--獲取html表格元素 --> var tab = document.getElementById("test"); <!--將每個單元格元素進行取值,並以字典形式傳給后台 --> var data = { "ID":tab.rows[rownum].cells[0].innerHTML, "網絡IP":tab.rows[rownum].cells[1].innerHTML, "地址":tab.rows[rownum].cells[2].innerHTML, "責任人":tab.rows[rownum].cells[3].innerHTML, "聯系方式":tab.rows[rownum].cells[4].innerHTML, }; alert("提交成功!") $.ajax({ type: "get", url: "/edit", data: data, dataType: "json" }); }); })();
(2)后台對提交后的數據進行讀取,並寫數據庫
@app.route('/edit', methods=['get']) def edit(): label = ['ID', '網絡IP', '地址', '責任人', '聯系方式'] content = [request.args.get(i) for i in label] print(content) sql = 'update {0} set {1}="{6}",{2}="{7}",{3}="{8}",{4}="{9}" where {5}={10}'.format('material_table', label[1], label[2], label[3],label[4],label[0],content[1],content[2],content[3],content[4],content[0]) cur = con.cursor() cur.execute(sql) con.commit() return "數據寫入成功!"
在實現“提交”功能時,我主要遇到了以下幾個 坑:
(1)html代碼寫完后,發現程序報錯,提示$.ajax is not a function。我去,我看其他大神的數據交互也是這么寫的呀,為什么我這不行?
查看網上的帖子,都是說未定義或者和其他庫有沖突,最后我自己發現,是因為我沒有聲明是JQuery。需要在script前面加上一行代碼:
<script src="http://libs.baidu.com/jquery/1.9.1/jquery.min.js"></script>
我理解這行代碼的意思是聲明下面要JQuery庫,而不是其他JS庫。(可能理解有誤)
最后加上這行代碼后,問題成功解決!
(2)獲取當前行號
一開始在獲取行號,怎么獲取不到,而且不知道要怎么調試,在同事的指導下,才學會通過alert(td.innerHTML)來查看獲取的當前行內容是什么。
最初從網上 查到獲取當前行的寫法是:
var td = event.parentElement; var rownum = td.parentElement.rowIndex;
通過alert調試,發現點擊提交根本沒有反應;又改成
var td = event.srcElement; var rownum = td.parentElement.rowIndex;
結果是獲取不到任何內容
就這么個小問題就花費了我近2個小時的時間去不停地查資料,嘗試編寫。最后想說的是,如果對html不熟悉,還是應該找個大神帶帶自己的。
最后在別人的協助下,實現了獲取當前行的功能:
(3)獲取每個表格里的 內容
tab.rows[0].cells[0].innerHTML
在獲取單元格內數據時,最驗證的是我獲取不到tab,即表格元素。因為我原先沒有在表格元素里加id,即
網上找了很多方法都沒法實現,最后老老實實地加上 id="test"
講道理,html里的這 20行代碼是我搞這個表格管理平台時,花費最大精力的。至此,表格管理平台的功能基本成行 !
【第五步】添加新增功能
以上功能只實現了對現有數據的編輯保存功能,但是如果用戶想要新增數據,怎么辦?我當時第一個想法是讓用戶自己去改數據庫,哈哈。還要我去寫新增功能,要累死了,不想寫。
下面是關於新增功能的介紹和示例代碼。
1、如何添加“新增”按鈕
<td><input type="button" value="新增" id="create"></td><br>
如果前面 的html能看懂了,這行是不難理解的。
2、點擊新增按鈕后,如何動態增加表格行、列
<script> (function () { $('input[id="create"]').on('click', function(){ var editTable=document.getElementById("tbody"); var tr=document.createElement("tr"); var td1=document.createElement("td"); td1.innerHTML=""; tr.appendChild(td1); editTable.appendChild(tr);
首先定義tr元素,然后在tr元素中再追加td元素。如果表格里有多列數據,那只需要重復td1的寫法,進行復制粘貼就可以了。
另外,當前td.innerTHML是設置為空,如果要將該單元格直接設置為編輯狀態,則修改成 :
td1.innerHTML="input[type=text] /";
3、如何動態添加“編輯”、“提交”按鈕,下面以“編輯”為例
var td9 = document.createElement("td") var myedit =document.createElement("input"); myedit.type = "button"; myedit.value = "編輯" myedit.id = "edit" td9.appendChild(myedit)
添加方式和添加文本框方式是一樣的,只是需要注意元素類型是Input,並且要補充下元素的type/value/id。
4、如何對動態添加的按鈕進行事件綁定,下面以提交功能為例
$('input[id="submit"]').on('click', function(){ alert("test") }
關於動態添加的按鈕進行事件綁定有很多帖子,有用Live方法的,有用$(document).on('click','.edit',function()方法的,其實不用這么麻煩,和正常的“提交”寫法是完全一樣的。
5、獲取當前新增行內的數據,進行提交。
var tab = document.getElementById("test"); var rownum = td1.parentElement.rowIndex; $('input[id="submit"]').on('click', function(){ var data = { "ID":tab.rows[rownum].cells[0].innerHTML, }; alert("新增成功!") $.ajax({ type: "get", url: "/create", data: data, dataType: "json" }); });
這段代碼和提交功能的實現是一樣的,大同小異。
本文分享自華為雲社區《【Python成長之路】從 零做網站開發 -- 基於Flask和JQuery,實現表格管理平台》,原文作者: 鵬哥賊優秀 。