本文主要介绍把 Flask-SQLAlchemy 代码进行模块化划分的时候,需要注意的问题。
如果把 Flask-SQLAlchemy 的代码全部放在一个文件中,示例代码如下:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
import os
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DB_URI')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db = SQLAlchemy(app)
class Users(db.Model):
id = db.Column(db.Integer, nullable=False, primary_key=True)
name = db.Column(db.String(20), nullable=False)
def __repr__(self):
return '<User %r>' % self.name
if __name__ == '__main__':
db.create_all()
我们的目的是创建数据库和数据库表。以上代码有如下几个要点:
- Flask-SQLAlchemy 的数据库连接 uri 写在
app.config配置中,这是一个 dict 类型的结构,KEY 为SQLALCHEMY_DATABASE_URI。Python 3.2 之后,不能用 MysqlDb 模块连接数据库,要使用 PyMysql 模块。SQLALCHEMY_DATABASE_URI的写法为:
mysql+pymysql://username:password@server_name:3306/database_name?charset=utf8
-
create_all()方法不能在 MySQL 数据库自动创建数据库,需要手工创建。在网上搜索,没有找到自动创建的解决方法 -
create_all()方法在创建表的时候,如果数据库表已经存在,则模型的改动不会作用于实际的表,要先调用drop_all()方法然后再调用create_all()方法进行覆盖
现在我们假设考虑工程的文件结构模块化,工程文件结构如下:
flask_sqlalchemy_test /
app /
__init__.py
models.py
create_table.py
首先在 app/models.py 中编写如下代码:
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
class Users(db.Model):
id = db.Column(db.Integer, nullable=False, primary_key=True)
name = db.Column(db.String(16), nullable=False)
def __repr__(self):
return '<User %r>' % self.name
然后在 app/__init__.py 中编写如下代码:
from flask import Flask
import os
from app.models import db
def create_app():
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = os.getenv('DB_URI')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
db.init_app(app)
return app
说明:在 models.py 中定义 db: db = SQLAlchemy() ,没有初始化 app,而是在 create_app() 函数中,通过 db.init_app() 方法初始化 app。
然后在 create_table.py 中调用代码创建数据库表:
from app.models import db
from app import create_app
app = create_app()
if __name__ == '__main__':
db.create_all()
我们试着运行一下,Oops,出现了如下错误:
RuntimeError: application not registered on db instance and no application bound to current context
出现错误的原因是 Flask 允许多个 app 同时存在,所以有 application context 的概念,db.init_app() 的时候,并不清楚要初始化哪一个 app,我们需要在 init_app() 在这个语句之前,要加上一行代码,像下面这样:
db.app=app #<------------<<
db.init_app(app)










网友评论