在“FlaskWeb開發:基於Python的Web應用開發實戰“一書中,作者為了簡便以及更側重於Flask而不是數據庫的說明,所以書中使用了SQLite數據庫。
但是實際應用中mySQL應該更廣泛一些。所以嘗試使用mySQL替代書中原代碼中SQLite數據庫的功能。
平台說明:
Ubuntu 16.04 4.8.0-36-generic (安裝在VMware上)
- 第一個需要注意的就是,與SQLite不同的是,Flask-SQLAlchemy並不會為mySQL主動去建立一個database。所以需要自己手動在mySQL中建立一個相應的數據庫,然后才能使用Flask-SQLAlchemy對相應數據進行查找,驗證等操作。如果沒有事先創建,是不能使用mySQL的。
所以第一個步驟就是在mySQL上創建數據庫,這里使用sql腳本進行創建,並且使用的是本機的mySQL。
使用命令:mysql -u root -p
然后輸入安裝mySQL時設置的密碼登入mySQL。
然后使用命令:source data_test.sql執行事先寫好的sql腳本,創建相應數據庫。這里我是在腳本目錄執行的,如果不是需要指定完整路徑。
data_test.sql文件內容如下。該腳本與書中的models.py內容對應。表,表頭一一對應,但是功能不一定能一一對應,對mySQL不是很熟悉。
1 drop database if exists data_test; 2 create database data_test; 3 use data_test; 4 CREATE TABLE roles( 5 id INT(11) NOT NULL AUTO_INCREMENT, 6 name VARCHAR(255) COLLATE utf8_bin NOT NULL, 7 UNIQUE (name), 8 permissions INT(11), 9 `default` BOOLEAN DEFAULT FALSE, 10 INDEX(`default`), 11 PRIMARY KEY (id) 12 ) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin 13 AUTO_INCREMENT=1; 14 15 CREATE TABLE users( 16 id INT(11) NOT NULL AUTO_INCREMENT, 17 username VARCHAR(255) COLLATE utf8_bin NOT NULL, 18 UNIQUE (username), 19 email VARCHAR(255) COLLATE utf8_bin NOT NULL, 20 UNIQUE (email), 21 INDEX(username,email), 22 password_hash VARCHAR(255) COLLATE utf8_bin NOT NULL, 23 role_id INT(11), 24 confirmed BOOLEAN DEFAULT FALSE, 25 name VARCHAR(255), 26 location VARCHAR(255), 27 about_me TEXT, 28 member_since datetime DEFAULT CURRENT_TIMESTAMP, 29 last_seen datetime DEFAULT CURRENT_TIMESTAMP, 30 avatar_hash VARCHAR(255), 31 followed INT(11), 32 followers INT(11), 33 FOREIGN KEY (role_id) REFERENCES roles(id) ON DELETE CASCADE, 34 PRIMARY KEY (id) 35 ) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin 36 AUTO_INCREMENT=1; 37 38 CREATE TABLE posts( 39 id INT(11) NOT NULL AUTO_INCREMENT, 40 body TEXT, 41 body_html TEXT, 42 timestamp datetime DEFAULT CURRENT_TIMESTAMP, 43 INDEX(timestamp), 44 author_id INT(11), 45 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE, 46 PRIMARY KEY (id) 47 ) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin 48 AUTO_INCREMENT=1; 49 50 CREATE TABLE follows( 51 follower_id INT(11), 52 constraint con_follower FOREIGN KEY (follower_id) REFERENCES users(id), 53 followed_id INT(11), 54 constraint con_followed FOREIGN KEY (followed_id) REFERENCES users(id), 55 PRIMARY KEY (follower_id,followed_id), 56 timestamp datetime DEFAULT CURRENT_TIMESTAMP 57 )ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin; 58 59 CREATE TABLE comments( 60 id INT(11) NOT NULL AUTO_INCREMENT, 61 body TEXT, 62 body_html TEXT, 63 timestamp datetime DEFAULT CURRENT_TIMESTAMP, 64 INDEX(timestamp), 65 disabled BOOLEAN, 66 author_id INT(11), 67 post_id INT(11), 68 FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE CASCADE, 69 FOREIGN KEY (post_id) REFERENCES posts(id) ON DELETE CASCADE, 70 PRIMARY KEY (id) 71 ) ENGINE=INNODB DEFAULT CHARSET=utf8 COLLATE=utf8_bin 72 AUTO_INCREMENT=1;
執行后,mySQL應該可以查詢到新建的表。
- config文件中對數據庫進行設置
SQLALCHEMY_DATABASE_URI 使用的如下配置:
class TestingConfig(Config):
TESTING = True
SQLALCHEMY_DATABASE_URI = "mysql+pymysql://root:password@localhost:3306/data_test"
然后就可以使用Flask-SQLAlchemy對數據庫進行操作,而不必去mySQL中操作了。
整個過程中對我來說,比較困難的應該算是將Flask-SQLAlchemy中的關系映射到mySQL數據庫中,其中有個地方值得注意:
- SQLAlchemy中的relationship。
例如:roles表中有users = db.relationship('User', backref='role', lazy='dynamic')這句。對應到mySQL其實就是一個外鍵,並且是在users表中定義的,即users中的role_id都必須是從表roles的id字段中引用過來的。如果在users中添加一個role,並且其id並不存在與role中,那么就會報錯。
其中的參數backref表明該關系為雙向,這樣就不需要再users再定義一個relationship了。而lazy設為dynamic即表明查詢的時候不直接加載結果,而是返回一個查詢對象,這樣就可以加過濾對查詢結果進行篩查。
實踐過程中參考了下面鏈接: