flask mysql环境配置_Flask教程4:数据库

b630271ecf7ca564f35e104b5af61d01.png

Flask中的数据库

Flask并不原生支持数据库,而是通过Python包以及Flask数据库插件。

数据库分为关系型数据库和非关系型数据库,这里我们使用关系型数据库。我们使用Flask-SQLAlchemy插件,它是SQLAlchemy的Flask插件包,基于对象关系映射ORM。SQLAlchemy支持很多数据引擎,包括MySSQL、PostgreSQL、SQLite等。通过下面的命令安装Flask-SQLAlchemy插件:

(venv) $ pip install flask-sqlalchemy

数据迁移

大部分数据库教程都是关于创建数据库,使用数据库的,很少有讲解对已有的数据库进行升级改造的。关系型数据库如果需要改变结构,需要进行数据迁移,这需要Flask-Migrate,一个SQLAlchemy的迁移工具。安装方式:

(venv) $ pip install flask-migrate

Flask-SQLAlchemy配置

这里我用了SQLite数据库,只需要一个本地文件,而不用安装MySQL数据库。我们在config.py中增加配置如下:

import os
basedir = os.path.abspath(os.path.dirname(__file__))

class Config(object):
    # ...
    SQLALCHEMY_DATABASE_URI = os.environ.get('DATABASE_URL') or 
        'sqlite:///' + os.path.join(basedir, 'app.db')
    SQLALCHEMY_TRACK_MODIFICATIONS = False

SQLALCHEMY_DATABASE_URI指定了数据库文件的存储位置,SQLALCHEMY_TRACK_MODIFICATIONS屏蔽了不需要的Flask-SQLAlchemy的数据够新通知特性。

数据库实例

在应用中,数据库用实例表示,我们在app/init.py文件中进行实例化:

from flask import Flask
from config import Config
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

app = Flask(__name__)
app.config.from_object(Config)
db = SQLAlchemy(app) # 数据库实例
migrate = Migrate(app, db) # 数据迁移引擎实例化

from app import routes, models # models定义数据库结构,对应下面新建的models.py。

数据库模型

借助SQLAlchemy数据在应用中表示成不同的类,SQLAlchemy负责将这些类表达成表。用户表的设计如下:

b5e8c3ca59299df081c66e08a6f27ab0.png

出于安全考虑,这里并没有明文存储用户密码。

新建app/models.py用以管理数据库,内热如下:

from app import db

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True) # 数据列
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))

    def __repr__(self): # 字符串显示方法
        return '<User {}>'.format(self.username)

创建数据迁移仓库

如果需要对数据库的结构进行改变,需用上数据迁移工具。运行flask db init命令,可以自动创建当前版本的数据迁移脚本。

(venv) $ flask db init
  Creating directory /home/miguel/microblog/migrations ... done
  Creating directory /home/miguel/microblog/migrations/versions ... done
  Generating /home/miguel/microblog/migrations/alembic.ini ... done
  Generating /home/miguel/microblog/migrations/env.py ... done
  Generating /home/miguel/microblog/migrations/README ... done
  Generating /home/miguel/microblog/migrations/script.py.mako ... done
  Please edit configuration/connection/logging settings in
  '/home/miguel/microblog/migrations/alembic.ini' before proceeding.

在项目目录中,增加了一个migrations的文件夹,其中的文件应加入git进行跟踪。

数据迁移

有了数据迁移仓库就有了数据迁移脚本,我们可以进行第一次数据迁移,即创建用户数据表,这有两种方法:自动方法和手动方法。对于自动方法,Alembic会比较数据模型和数据库内的数据表,在数据迁移脚本中增加数据迁移命令。当前没有数据表,所以在数据迁移脚本中会增加在数据库中创建数据表的命令。修改数据迁移脚本命令如下:

(venv) $ flask db migrate -m "users table"
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'user'
INFO  [alembic.autogenerate.compare] Detected added index 'ix_user_email' on '['email']'
INFO  [alembic.autogenerate.compare] Detected added index 'ix_user_username' on '['username']'
  Generating /home/miguel/microblog/migrations/versions/e517276bb1c2_users_table.py ... done

命令中的-m "users table" 是可选的,起到注释作用。这条命令只是产生了一个py文件,用来进行数据迁移,并没有修改数据库。要修改数据库,需要运行如下命令:

(venv) $ flask db upgrade
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade  -> e517276bb1c2, users table

如果你使用了Mysql或者PostgreSQL,在运行flask db upgrade之前应该先创建user表。Flask-SQLAlchemy会根据数据类的名称自动转换和创建数据表名称,日如User类编程user表,AddressAndPhone类变成address_and_phone表。如果需要另选表名称,可以在数据类中增加__tablename__参数。

数据库升级和降级

在实际工作中可能存在一个开发环境(本机)和一个在线环境(服务器)。如果你开发的新版应用需要修改表结构,那么你运行flask db migrate可以自动产生数据迁移的命令。在git中更新后,在线环境直接运行flask db upgrade就能同步升级数据库。

如果你发现新部署的应用有问题,可以用flask db downgrade回退到上一个版本。

数据表关系

关系型数据库的表之间存在联系,比如博客中的文章需要记录是谁发布的,或者查询一个用户发了哪些帖子。我们增加一个post表用来记录帖子。

ddbc613c96c75d43529dd73edbf0989f.png

帖子表中的user_id是一个外键,用来和用户表进行连接,这种连接是一种一对多的连接。我们修改app/models.py如下:

from datetime import datetime
from app import db

class User(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(64), index=True, unique=True)
    email = db.Column(db.String(120), index=True, unique=True)
    password_hash = db.Column(db.String(128))
    posts = db.relationship('Post', backref='author', lazy='dynamic')# 新增一个数据视图

    def __repr__(self):
        return '<User {}>'.format(self.username)

class Post(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    body = db.Column(db.String(140))
    timestamp = db.Column(db.DateTime, index=True, default=datetime.utcnow) # 默认值传递一个函数
    user_id = db.Column(db.Integer, db.ForeignKey('user.id')) # 外键

    def __repr__(self):
        return '<Post {}>'.format(self.body)

在更新了应用中的数据模型后,需要产生新的数据迁移脚本:

(venv) $ flask db migrate -m "posts table"
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.autogenerate.compare] Detected added table 'post'
INFO  [alembic.autogenerate.compare] Detected added index 'ix_post_timestamp' on '['timestamp']'
  Generating /home/miguel/microblog/migrations/versions/780739b227a7_posts_table.py ... done

然后执行数据迁移脚本,实际修改数据:

(venv) $ flask db upgrade
INFO  [alembic.runtime.migration] Context impl SQLiteImpl.
INFO  [alembic.runtime.migration] Will assume non-transactional DDL.
INFO  [alembic.runtime.migration] Running upgrade e517276bb1c2 -> 780739b227a7, posts table

记得把这些数据迁移脚本加入git。

说明

本文是我的Flask学习笔记,原教程地址:https://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-iv-database

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值