在“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:[email protected]: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即表明查询的时候不直接加载结果,而是返回一个查询对象,这样就可以加过滤对查询结果进行筛查。
实践过程中参考了下面链接: