Windows 10家庭中文版,Python 3.6.4,Flask 1.0.2html
本文介紹了第一次在Flask框架中操做SQLite3數據庫的測試,參考了官網的文檔Using SQLite 3 with Flask,直接使用了裏面定義前端
的幾個函數:init_db、get_db、close_connection、make_dicts,另外,本身編寫了視圖(View)函數實現添加、讀取操做。sql
本測試項目的目標數據庫
-使用建模文件初始化數據庫成功flask
-鏈接數據庫成功api
-關閉數據庫成功瀏覽器
-添加數據成功session
-讀取數據成功,併成功返回到頁面app
測試步驟框架
1.創建空的SQLite3數據庫文件 和 數據庫建模文件
前面一篇關於SQLite3的文章有介紹,使用sqlite3.exe便可;
數據庫建模文件,參考SQLite官方文檔SQL As Understood By SQLite創建;
下面是個人建模文件內容:
1 DROP TABLE IF EXISTS post; 2 CREATE TABLE post ( 3 id INTEGER PRIMARY KEY AUTOINCREMENT, 4 body VARCHAR(500) NOT NULL, 5 created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP 6 );
若是原數據庫存在,就刪除,而後創建新的。
數據表post,包括id、body、created三個字段,其中,body字段爲提交的消息,created爲消息存放到數據庫的時間。
創建好的數據庫文件和建模文件放到項目的db文件夾下:
說明,數據庫文件和建模文件不必定要放到db文件夾下,也能夠放到Flask項目的根目錄下(Q:是否能夠放到項目以外呢?不建議。),只要程序中把相關路徑輸入正確便可。
2.編寫Flask項目文件main.py(單模塊項目)
將文檔Using SQLite 3 with Flask中的一些代碼拷貝到many.py中。
1 from flask import * # 導入flask模塊下的全部元素 2 import sqlite3 # 導入sqlite3模塊 3 4 app = Flask('Posts') # 創建Flask應用 5 6 DATABASE = 'db/posts.db' # 數據庫文件地址 7 DATABASE_INIT_FILE = 'db/init.sql' # 數據庫建模文件地址 8 9 # init_db() 10 def init_db(): # 此函數要使用 數據庫建模文件 初始化數據庫:創建post表(Initial Schemas)。此函數在命令行中使用,僅一次,再次使用會刪除數據庫中已有數據。 11 with app.app_context(): # 官網文檔說了緣由:不是在Web應用中使用,而是在Python Shell中使用時須要此語句(Connect on Demand)。 12 db = get_db() 13 with app.open_resource(DATABASE_INIT_FILE, mode='r') as f: # with語句用法! 14 db.cursor().executescript(f.read()) # 執行建模文件中的腳本 15 db.commit() # 提交事務 16 17 # make_dicts() 18 def make_dicts(cursor, row): # 將查詢返回的數據的轉換爲字典類型,這樣會跟方便使用。此函數會在get_db()函數中用到,賦值給db.row_factory。 19 return dict((cursor.description[idx][0], value) 20 for idx,value in enumerate(row)) 21 22 # get_db() 23 def get_db(): # 獲取數據庫鏈接 24 db = getattr(g, '_database', None) # g對象時一個Flask應用的公共對象(和request、session同樣),用於存儲用戶的數據——整個應用共享! 25 if db is None: 26 db = g._database = sqlite3.connect(DATABASE) # 創建數據庫鏈接 27 db.row_factory = make_dicts # 轉換默認的查詢數據類型爲字典類型,也可使用sqlite3.Row 28 return db # 返回數據庫鏈接,可能返回爲None 29 30 # close_connection() 31 @app.teardown_appcontext # 這個裝飾器用於實如今請求的最後自動關閉數據庫鏈接的功能 32 def close_connection(exception): # 關閉數據庫鏈接 33 db = getattr(g, '_database', None) 34 if db is not None: 35 db.close()
說明,在謄寫代碼過程當中,把cursor.description寫錯了,直到最後運行程序才發現了錯誤。
以上,初始化數據庫——只執行一次、獲取數據庫鏈接、關閉數據庫鏈接的程序都有了。接下來,創建一個視圖函數測試數據庫鏈接、關閉數據庫鏈接是否正常執行。
注意,在此時以前須要再get_db、close_connection函數中添加調試語句,print或者app.logger均可以。
1 @app.route('/testdb') 2 def testdb(): 3 get_db() 4 return "After test"
而後,啓動Flask項目,使用瀏覽器訪問/testdb,檢查項目命令行便可看到添加的調試語句——提示錯誤就繼續修改。
3.使用 建模文件 初始化 數據庫文件
這個時候須要用到上面的init_db()函數了。
在文檔Using SQLite 3 with Flask的Initial Schemas中有介紹,將Flask項目模塊的init_db()函數導入,再執行便可。
下面是個人測試狀況:成功 按照建模文件 創建 數據表post
注意,在Python Shell執行上面的命令時,須要保證當前目錄爲Flask項目所在目錄。
4.創建測試項目須要視圖函數(View functions)
本測試項目須要實現發佈消息、展現消息的功能(但並無作到同一個頁面上),所以,創建了三個視圖函數來實現目標:
4.1 home()
首頁,返回一個模板用於添加post。
此模板文件僅包含靜態內容,所以,render_template只有一個參數。
1 # path: / 2 # show posts 3 @app.route('/') 4 def home(): 5 return render_template('temp.html')
模板文件主要內容:定義表單,action爲「pureadd」
1 <form action="pureadd" method="post"> 2 <textarea name="newpost" style="width:200px;height:100px;" maxlength="500"></textarea><br /> 3 <input type="submit" value="添加" /> 4 </form> 5 <a href="/pureshow">展現帖子</a><br />
頁面以下:
4.2 pureadd()
一個單純地(pure)用於添加一條post到數據庫的視圖函數,會對參數進行校驗、發生錯誤時會返回錯誤的信息等。
僅支持POST方法的請求。
此視圖的返回信息中還包括跳轉到添加頁面、展現頁面的連接。
1 # pure add page for test 2 @app.route('/pureadd', methods=['POST']) 3 def pureadd(): 4 # step 1. get the new post and check the data 5 newp = '' 6 try: 7 newp = request.form['newpost'] 8 except: 9 return 'ERROR: Invalid form parameters!' 10 11 print('newp = "', newp, '"') 12 13 newp2 = newp.strip() # 清理post兩遍的空格,而後賦值給新變量——此時舊變量沒有改變 14 15 if newp2 == '': 16 return 'Warning: New post is empty!<br/>' \ 17 '<a href="/">繼續添加</a><br/>' \ 18 '<a href="/pureshow">展現帖子</a><br />' 19 20 # step 2.write the new post into database 21 sqlmode = 'INSERT INTO post(body) VALUES(?)' # 添加數據的SQL語句,佔位符使用問號(?)。須要注意的是,若是是MySQL,佔位符是百分號(%)。 22 try: 23 db = get_db() 24 cursor = db.cursor() 25 cursor.execute(sqlmode, (newp2,)) 26 cursor.close() # 關閉cursor。Q:是否必定要關閉呢?不關閉有什麼影響? 27 db.commit() # 須要commit,不然,數據不會更新到數據庫 28 except Exception as e: 29 return '<span style="color:red;">INFO: New post added failed <br/> %s</span><br/>' \ 30 '<a href="/">繼續添加</a><br/>' \ 31 '<a href="/pureshow">展現帖子</a><br />' % str(e) 32 else: 33 return 'INFO: New post added <br/><pre>[%s]</pre><br/>' \ 34 '<a href="/">繼續添加</a><br/>' \ 35 '<a href="/pureshow">展現帖子</a><br />' % newp
成功添加一條數據:
數據庫中顯示添加的數據:
4.3 pureshow()
此視圖函數用於 展現數據庫中的數據。
將查詢到的數據直接返回到 模板文件showall.html 中。
注意,須要提一下前面get_db()函數中的設置db.row_factory爲make_dicts。若是沒有這個賦值的話,模板文件的解析數據方式將會改變。
1 # pure show page for test 2 @app.route('/pureshow') 3 def pureshow(): 4 sqlmode = "SELECT * FROM post ORDER BY created DESC" 5 rv = [] 6 try: 7 db = get_db() 8 cursor = db.execute(sqlmode) 9 rv = cursor.fetchall() 10 cursor.close() 11 except Exception as e: 12 print(e) 13 abort(500) 14 else: 15 return render_template('showall.html', posts=rv)
模板文件showall.html的主要內容:使用for循環將pureshow()函數返回的內容展現出來
1 <div id="postslist"> 2 {% for post in posts %} 3 <div class="post_item" id="post{{ post.id }}"> 4 {{ post.body }}<br/> 5 {{ post.created }} 6 </div> 7 {% endfor %} 8 </div> 9 <a href="/">繼續添加</a>
/pureshow頁面展現內容以下:
注意,數據庫中保存的時間爲UTC時間,在實際應用中,展現出來時還須要添加對應的時差。
參考連接
後續
上面的方法很簡單,在Flask提供的擴展中,有一個叫作SQLAlchemy的,使用它能夠更高效地操做各類數據庫,因此,下一步就是學習並使用它了。
官方文檔SQLAlchemy in Flask中有介紹,看過一遍了,如今,該實踐了。
前面作的項目都是基於單個的模型文件的,後面須要升級:基於package的方式、使用Blueprint,這兩個是重點啊!
在官網的Tutorial會有關於SQLAlchemy、Blueprint的介紹,也是須要參考的。
Flask,還須要以周計的時間才能熟練使用啊。
本身沒有作過完整的Web應用,在URL設計等方面存在一些挑戰,所以,這個測試項目纔會如此simple。
原本還想實現用戶登陸、退出等「稍微複雜」的功能的——最初的想法,最後都只能放棄了。
我想,在熟悉了SQLAlchemy、Blueprint後,Web開發的功力會有很大提升的。
對了,還有就是 怎麼提供數據接口給前端,好比RESTful API等,都是須要熟練的。