在Flask中使用mySQL

在“FlaskWeb开发:基于Python的Web应用开发实战“一书中,作者为了简便以及更侧重于Flask而不是数据库的说明,所以书中使用了SQLite数据库。

但是实际应用中mySQL应该更广泛一些。所以尝试使用mySQL替代书中原代码中SQLite数据库的功能。

平台说明:

Ubuntu 16.04 4.8.0-36-generic (安装在VMware上)

  1. 第一个需要注意的就是,与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应该可以查询到新建的表。

     

  2. 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即表明查询的时候不直接加载结果,而是返回一个查询对象,这样就可以加过滤对查询结果进行筛查。

实践过程中参考了下面链接:

对外建的理解

外键constraint关键字

 

posted @ 2018-03-14 12:02  谢世倾  阅读(5324)  评论(0编辑  收藏  举报