Flask學習之旅--資料庫
一、寫在前面
在Web開發中,資料庫操作是很重要的一部分,因為網站的很多重要資訊都儲存在資料庫之中。而Flask在預設情況下是沒有資料庫、表單驗證等功能的,但是可以用Flask-extension為Web應用新增這些功能。
二、Flask SQLite
SQLite是一款輕型的資料庫,是遵守ACID的關係型資料庫管理系統。由於Python對SQlite有內建的支援,因此在Flask應用程式中和SQLite進行互動是比較容易的。
首先需要建立一個SQLite資料庫“user.db”,並在其中建立一張使用者表。程式碼如下:
1 import sqlite3 2 3 4 conn = sqlite3.connect("user.db") 5 print("Connected!") 6 7 conn.execute("CREATE TABLE USER(username TEXT, password TEXT, EMAIL TEXT)") 8 print("Table created successfully!") 9 conn.close()
這裡就不貼HTML程式碼了,就是一個註冊頁面,在註冊的時候會將使用者輸入的使用者名稱、密碼和郵箱傳到後臺。在app.py中需要匯入sqlite3模組,然後連線前面建立的user.db,在建立連線之後建立一個遊標物件,然後編寫SQL語句進行資料庫操作,整個過程都算是比較容易的。app.py中的程式碼如下:
1 from flask import Flask, render_template, request 2 import sqlite3 as sql 3 4 app = Flask(__name__) 5 6 7 @app.route('/register', methods=['GET', 'POST']) 8 def register(): 9 if request.method == 'GET': 10 return render_template('register.html') 11 else: 12 msg = "" 13 try: 14 username = request.form["usr"] 15 password = request.form["pwd"] 16 email = request.form["email"] 17 print(username, password, email) 18 with sql.connect("user.db") as con: 19 cur = con.cursor() 20 cur.execute("INSERT INTO USER (username, password, email) VALUES (?,?,?)", 21 (username, password, email)) 22 con.commit() 23 msg = "註冊成功!" 24 except: 25 con.rollback() 26 msg = "註冊失敗!請重試!" 27 finally: 28 con.close() 29 return render_template('register.html', msg=msg) 30 31 32 if __name__ == '__main__': 33 app.run()
三、Flask SQLAlchemy
Flask-SQLAlchemy是Flask擴充套件,它將對SQLAlchemy的支援新增到Flask應用程式中。在Flask Web應用程式中使用原始SQL對資料庫執行CRUD操作可能很繁瑣,不過SQLAlchemy 為應用程式開發人員提供了SQL的全部功能和靈活性。它是一個對資料庫的抽象,讓開發者不用這些編寫SQL語句,而是使用其提供的介面去操作資料庫,這其中涉及到一個非常重要的思想:ORM(Object Relation Mapping,物件關係對映),主要的功能是實現模型物件到關係型資料庫資料的對映。說白了就是使用通過物件去操作資料庫。
1.Flask-SQLAlchemy安裝
使用pip install flask-sqlalchemy進行安裝。不過在安裝的時候可能會出現如下錯誤:
pip._vendor.urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Read timed out.
這是因為在下載python庫的時候,由於國內網路原因,導致python包的下載速度非常慢,檢視pip 文件,只要在 pip的時候控制超時即可, 具體引數為 --default-timeout=100, 後面的時間可以自己指定。因此可以用如下命令進行下載安裝:
pip install --default-timeout=100 flask-sqlalchemy
2.Flask-SQLAlchemy配置
從此模組匯入SQLAlchemy類,建立一個Flask應用程式物件併為要使用的資料庫設定URI的程式碼如下:
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# URI的格式為:使用者名稱:密碼@ip地址:埠號(預設可以不寫)/資料庫名app.config['SQLALCHEMY_DATABASE_URI'] = "mysql://root:qwer1234@localhost/flask"
3.配置的時候可能出現的問題及解決辦法
1)ModuleNotFoundError: No module named 'MySQLdb'
解決辦法:
使用pymysql模組,URI改為:
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+pymysql://root:qwer1234@localhost/flask"
2)Warning: (1366, "Incorrect string value: '\\xD6\\xD0\\xB9\\xFA\\xB1\\xEA...' for column 'VARIABLE_VALUE' at row 481")
解決辦法:
改用mysql-connector,使用pip install mysql-connector下載安裝,URI改為:
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+mysqlconnector://root:qwer1234@localhost/flask"
3)sqlalchemy.exc.NotSupportedError: (mysql.connector.errors.NotSupportedError) Authentication plugin 'caching_sha2_password' is not supported
解決辦法:
出現這個錯誤是因為MySQL8.0採用了Use Strong Password Encryption for Authentication即強密碼加密,而mysql.connector的引擎不支援caching_sha2_password的加密格式,所以解決思路有如下幾種:
(1)重灌MySQL,在Authentication Method中選擇第二項(重灌比較麻煩,我就沒有嘗試):
(2)在client端,將加密格式選擇成mysql_native_password,命令如下(個人嘗試後無效):
ALTER user 'root'@'localhost' IDENTIFIED WITH mysql_native_password BY 'root'
(3)最後一種是我自己摸索出來的,就是在URI設定的時候加上一個引數auth_plugin並設定為mysql_native_password:
app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+mysqlconnector://root:qwer1234@localhost/flask?auth_plugin=mysql_native_password"
4.Flask-SQLAlchemy的基本操作
1) 常用查詢過濾器:
過濾器得到的還只是一些物件,需要使用執行器來獲取真正的資料。
filter()
: 把過濾器新增到原查詢上,返回一個新查詢,需要使用模型類名去獲取欄位來進行比較;
filter_by()
:把等值(只能使用=比較操作)過濾器新增到查詢上,返回一個新查詢;
order_by()
:根據指定條件對查詢結果進行排序,返回一個新查詢;
group_by()
:根據指定條件對原查詢結果進行分組,返回一個新查詢。
2.)常用查詢執行器
all()
:以列表的形式返回查詢的所有結果;
first()
:返回查詢的第一個結果;
first_or_404()
:同first(), 只不過如果沒有找到的話,返回404錯誤;
get()
:返回指定主鍵對應的行;
get_or_404()
:返回指定主鍵對應的行,如不存在,返回404錯誤;
count()
:返回查詢結果的數量;
paginate()
:返回一個Paginate物件,包含指定範圍內的結果。
3.)查詢條件
startswith('xx')
:查詢以xx開頭的所有資料;
endswith('xx')
:查詢以xx結尾的所有資料;
not_()
:取反;
and_()
:返回and()條件滿足的所有資料;
or_()
:返回or()條件滿足的所有資料。
5.使用示例
app.py中程式碼如下:
1 from flask_sqlalchemy import SQLAlchemy 2 import mysql.connector 3 4 5 app.config['SQLALCHEMY_DATABASE_URI'] = "mysql+mysqlconnector://root:qwer1234@localhost/flask?auth_plugin=mysql_native_password" 6 app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True 7 app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True 8 9 10 # 獲取SQLAlchemy例項物件 11 db = SQLAlchemy(app)
然後新建一個model.py,編寫如下程式碼進行測試:
1 from app import db 2 3 4 # 建立模型物件 5 class User(db.Model): 6 __tablename__ = "users" 7 id = db.Column(db.Integer, primary_key=True) 8 username = db.Column(db.String(16), unique=True) 9 password = db.Column(db.String(16)) 10 email = db.Column(db.String(32), unique=True) 11 12 def __repr__(self): 13 return '<User %r>' % self.username 14 15 16 # 1.建立表 17 db.create_all() 18 print("Created Successfully!") 19 20 # 2.增加記錄 21 usr1 = User() 22 usr1.id = 1 23 usr1.username = "wang" 24 usr1.password = "wangwang" 25 usr1.email = "[email protected]" 26 usr2 = User(id=2, username="yang", password="yang", email="[email protected]") 27 db.session.add(usr1) 28 print("Add usr1") 29 db.session.add(usr2) 30 print("Add usr2") 31 db.session.commit() 32 33 # 3.查詢記錄,注意查詢返回物件,如果查詢不到返回None 34 users1 = User.query.all() # 查詢所有 35 print(users1) 36 print("User Count:", len(users1)) 37 38 # 4.刪除 39 user = User.query.get(1) 40 db.session.delete(user) 41 print("Delete usr1") 42 db.session.commit() 43 44 users2 = User.query.all() # 查詢所有 45 print(users2) 46 print("User Count:", len(users2))
執行結果如下所示:
Created Successfully!
Add usr1
Add usr2
[<User 'wang'>, <User 'yang'>]
User Count: 2
Delete usr1
[<User 'yang'>]
User Count: 1
&n