解决有关Flask的循环引用问题【应用,蓝图,模型】

使用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 
    from .view.bp_insert import bp_insert
  File "D:\Code\Python\Flask-Demo\demo2\myapp\view\bp_insert.py", line 4, in 
    from ..model import *
  File "D:\Code\Python\Flask-Demo\demo2\myapp\model.py", line 4, in 
    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()

大功告成!

你可能感兴趣的:(flask,python,后端)