Flask:操作SQLite3(0.1)


Windows 10家庭中文版,Python 3.6.4,Flask 1.0.2

 

本文介紹了第一次在Flask框架中操作SQLite3數據庫的測試,參考了官網的文檔Using SQLite 3 with Flask,直接使用了里面定義

的幾個函數:init_db、get_db、close_connection、make_dicts,另外,自己編寫了視圖(View)函數實現添加、讀取操作。

 

本測試項目的目標

-使用建模文件初始化數據庫成功

-連接數據庫成功

-關閉數據庫成功

-添加數據成功

-讀取數據成功,並成功返回到頁面

 

測試步驟

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時間,在實際應用中,展示出來時還需要添加對應的時差。

 

參考鏈接

Using SQLite 3 with Flask

廖雪峰官網 之 使用SQLite(關於占位符)

 

后續

上面的方法很簡單,在Flask提供的擴展中,有一個叫做SQLAlchemy的,使用它可以更高效地操作各種數據庫,所以,下一步就是學習並使用它了。

官方文檔SQLAlchemy in Flask中有介紹,看過一遍了,現在,該實踐了。

 

前面做的項目都是基於單個的模型文件的,后面需要升級:基於package的方式使用Blueprint,這兩個是重點啊!

 

在官網的Tutorial會有關於SQLAlchemy、Blueprint的介紹,也是需要參考的。

 

Flask,還需要以周計的時間才能熟練使用啊。

 

自己沒有做過完整的Web應用,在URL設計等方面存在一些挑戰,因此,這個測試項目才會如此simple。

本來還想實現用戶登錄、退出等“稍微復雜”的功能的——最初的想法,最后都只能放棄了。

我想,在熟悉了SQLAlchemy、Blueprint后,Web開發的功力會有很大提高的。

 

對了,還有就是 怎么提供數據接口給前端,比如RESTful API等,都是需要熟練的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM