解决Flask-SQLAlchemy循环引用
解决Flask-SQLAlchemy循环引用
1.问题
新建一个
flask
项目,它的初始化项目为:$ tree
circular_references
├── app.py # 主 app 文件
├── static # css,js 文件目录
└── templates # 模板文件目录为了项目的健壮性,可以把
flask
的配置文件写入一个文件中config.py
此时实现一个如下的文件结构
$ tree
circular_references
├── app.py # 主 app 文件
├── config.py # Flask 配置文件
├── static # css,js 文件目录
└── templates # 模板文件目录
config.py
DEBUG = True # 开启Debug
TEMPLATES_AUTO_RELOAD = True # 模板自动加载
DB_URI = 'mysql+pymysql://root:[email protected]:3306/flask_alembic_demo' # 确保数据库存在
# 指定数据库连接
SQLALCHEMY_DATABASE_URI = DB_URI
SQLALCHEMY_TRACK_MODIFICATIONS = False
app.py
from flask import Flask
import config
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config.from_object(config)
db = SQLAlchemy(app)
class User2(db.Model):
__tablename__ = 'user2'
id = db.Column(db.Integer, primary_key=True, autoincrement=True, nullable=False)
name = db.Column(db.String(20))
# 创建数据库关系, 双向联系
addresses = db.relationship('Address2', back_populates='user')
class Address2(db.Model):
__tablename__ = 'address2'
id = db.Column(db.Integer, primary_key=True, autoincrement=True, nullable=False)
email_address = db.Column(db.String(45), nullable=False)
u_id = db.Column(db.Integer, db.ForeignKey('user2.id'))
# 创建数据库关系, 双向联系
user = db.relationship('User2', back_populates='addresses')
@app.route('/')
def hello_world():
return 'Hello World!'
if __name__ == '__main__':
app.run()随着项目的不断壮大,不可能把所有的
SQLAlchemy Model
都写入到app.py
主app
文件中,这时候就需要独立出一个文件专门存放Model
类models.py
circular_references
├── app.py # 主 app 文件
├── config.py # Flask 配置文件
├── models.py # 存放flask-sqlalchemy.Model 类
├── static # css,js 文件目录
└── templates # 模板文件目录这时候需要修改
app.py
和新建models.py
文件.
models.py
# models.py
from app import app
from flask_sqlalchemy import SQLAlchemy
db = SQlAlchemy(app)
class User2(db.Model):
__tablename__ = 'user2'
id = db.Column(db.Integer, primary_key=True, autoincrement=True, nullable=False)
name = db.Column(db.String(20))
# 创建数据库关系, 双向联系
addresses = db.relationship('Address2', back_populates='user')
class Address2(db.Model):
__tablename__ = 'address2'
id = db.Column(db.Integer, primary_key=True, autoincrement=True, nullable=False)
email_address = db.Column(db.String(45), nullable=False)
u_id = db.Column(db.Integer, db.ForeignKey('user2.id'))
# 创建数据库关系, 双向联系
user = db.relationship('User2', back_populates='addresses')# app.py
from flask import Flask
import config
from flask_sqlalchemy import SQLAlchemy
# 引入 User2,Address2
from models import User2,Address2
app = Flask(__name__)
app.config.from_object(config)
db = SQLAlchemy(app)
@app.route('/')
def hello_world():
return 'Hello World!'
# 假设需要一个与数据库交互的模板文件
@app.route('/add_user/')
def add_user():
"""引用ORM交互"""
u1 = User2(id=1, name='Jack')
a1 = Address2(id=1, email_address='[email protected]', u_id=1)
a2 = Address2(id=2, email_address='[email protected]', u_id=1)
a3 = Address2(id=3, email_address='[email protected]', u_id=1)
u1.addresses = [a1, a2, a3]
db.session.add(u1)
if __name__ == '__main__':
app.run()如果执行运行
app.py
文件,会产生一个循环引用 的报错ImportError: cannot import name 'db' from 'app'
产生的原因很简单,
python
代码是自上而下依次执行的.from models import user2
文件models.py
会先从app.py
中引入db
,才能生成User2
,这就是循环引入
2.解决循环引入
- END -为了解决他们之间的循环引入,这里需要引入第三个文件.
此时的目录结构如下
circular_references
├── app.py # 主 app 文件
├── config.py # Flask 配置文件
├── models.py # 存放flask-sqlalchemy.Model 类
├── ext.py # 存放 db
├── static # css,js 文件目录
└── templates # 模板文件目录
ext.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
# 不用绑定app,由 app.py 中绑定 app
models.py
# 从ext 中导入db
from ext import db
class User2(db.Model):
__tablename__ = 'user2'
id = db.Column(db.Integer, primary_key=True, autoincrement=True, nullable=False)
name = db.Column(db.String(20))
# 创建数据库关系, 双向联系
addresses = db.relationship('Address2', back_populates='user')
class Address2(db.Model):
__tablename__ = 'address2'
id = db.Column(db.Integer, primary_key=True, autoincrement=True, nullable=False)
email_address = db.Column(db.String(45), nullable=False)
u_id = db.Column(db.Integer, db.ForeignKey('user2.id'))
# 创建数据库关系, 双向联系
user = db.relationship('User2', back_populates='addresses')
app.py
from flask import Flask
import config
# 引入db
from ext import db
# 引入 User2,Address2
from models import User2,Address2
app = Flask(__name__)
app.config.from_object(config)
# 利用init_app()方法绑定app
db.init_app(app)
@app.route('/')
def hello_world():
return 'Hello World!'
# 假设需要一个与数据库交互的模板文件
@app.route('/add_user/')
def add_user():
"""引用ORM交互"""
u1 = User2(id=1, name='Jack')
a1 = Address2(id=1, email_address='[email protected]', u_id=1)
a2 = Address2(id=2, email_address='[email protected]', u_id=1)
a3 = Address2(id=3, email_address='[email protected]', u_id=1)
u1.addresses = [a1, a2, a3]
db.session.add(u1)
if __name__ == '__main__':
app.run()由于
python
自上而下执行,到执行User2()
函数时,它执行的是绑定app
的db
.
点击左下角查看更多