使用Flask时,如果同时使用主应用(_init_.py),实体类模型(model.py),蓝图(bp.py)的场景时,很容易导致循环引用
错误代码实例
_init_.py
from flask import Flask, Blueprint
from flask_sqlalchemy import SQLAlchemy
from .view.bp import bp # 这一句写在这里会报错的
# 主机名
HOSTNAME = '127.0.0.1'
# mysql端口号
PORT = 3306
# 用户名
USERNAME = '我的用户名'
# 密码
PASSWORD = '我的密码'
# 数据库名称
DATABASE = 'flask_demo'
# 主文件
app = Flask(__name__)
# 设置数据库配置,连接格式:dialect://username:password@host:port/database
# 下面是我的数据库参数,你要改成你的
app.config['SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}'
# mysql8版本以上url后面不需要加任何参数
db = SQLAlchemy(app) # 获取app中配置好的数据库
app.register_blueprint(bp)
if __name__ == '__main__':
app.run()
model.py
from . import db
class User(db.Model):
"""用户类"""
# 继承db.Model已经自动是实现了__init__方法
__tablename__ = 'user'
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(100), nullable=False)
password = db.Column(db.String(100))
def __repr__(self):
return f'User[{self.username} {self.password}]'
bp.py
from ..model import *
from flask import Blueprint
bp = Blueprint('bp', __name__, template_folder='templates')
# 插入一条数据
@bp.route('/add')
def add():
user = User(username='yuz', password='123456')
db.session.add(user)
# db.session.add(Article(name='Flask', author_id=1))
db.session.commit()
return '添加用户成功'
看上去似乎没有问题,但是产生了循环引用,并且报错:
Error: While importing 'myapp', an ImportError was raised:
Traceback (most recent call last):
File "F:\Environment\Anaconda3\lib\site-packages\flask\cli.py", line 218, in locate_app
__import__(module_name)
File "D:\Code\Python\Flask-Demo\demo2\myapp\__init__.py", line 8, in <module>
from .view.bp_insert import bp_insert
File "D:\Code\Python\Flask-Demo\demo2\myapp\view\bp_insert.py", line 4, in <module>
from ..model import *
File "D:\Code\Python\Flask-Demo\demo2\myapp\model.py", line 4, in <module>
from . import db
ImportError: cannot import name 'db' from partially initialized module 'myapp' (most likely due to a circular import) (D:\Code\Python\Flask-Demo\demo2\myapp\__init__.py)
这是因为
- init.py引用了bp.py的bp
- bp.py引用了model.py的User
- model.py引用了__init__.py的db
最终造成了循环引用
我的修改方式为移动引用,即移动_init_.py中from .view.bp import bp
到 使用db之后 的位置,但在使用bp之前
这是因为改正之后,先使用db,此时没有发生循环引用,这时候再使用bp,也不会发生循环调用
修改后_init_:
from flask import Flask, Blueprint
from flask_sqlalchemy import SQLAlchemy
# 主机名
HOSTNAME = '127.0.0.1'
# mysql端口号
PORT = 3306
# 用户名
USERNAME = '我的用户名'
# 密码
PASSWORD = '我的密码'
# 数据库名称
DATABASE = 'flask_demo'
# 主文件
app = Flask(__name__)
# 设置数据库配置,连接格式:dialect://username:password@host:port/database
# 下面是我的数据库参数,你要改成你的
app.config['SQLALCHEMY_DATABASE_URI'] = f'mysql+pymysql://{USERNAME}:{PASSWORD}@{HOSTNAME}:{PORT}/{DATABASE}'
# mysql8版本以上url后面不需要加任何参数
db = SQLAlchemy(app) # 获取app中配置好的数据库
from .view.bp import bp # 这一句写在这里才不会报错的
app.register_blueprint(bp)
if __name__ == '__main__':
app.run()
大功告成!