将我的模型移动到他们自己的模块会导致InvalidRequestError ..这似乎与数据库会话和我在模型模块中导入db的方式有关。
我尝试将此问题减少到必要的最少量代码。首先,一个工作的Flask应用程序:
import os
from flask import Flask, render_template, request
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SECRET_KEY'] = 'somesecret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(app.instance_path, 'app.db')
db = SQLAlchemy(app)
class Thing(db.Model):
id = db.Column(db.Integer, primary_key=True)
text = db.Column(db.String(300), nullable=False)
user_id = db.Column(db.Integer, db.ForeignKey('user.id'), nullable=False)
def __init__(self, user, text):
self.user = user
self.text = text
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True)
things = db.relationship('Thing', backref='user', lazy='dynamic')
def __init__(self, username):
self.username = username
@app.route('/', methods=['GET', 'POST'])
def add():
if request.method == 'POST':
username = request.form['username']
text = request.form['txt']
user = User.query.filter_by(username=username).first()
thing = Thing(user, text)
db.session.add(thing)
db.session.commit()
return render_template('index.html')
def initdb():
db.create_all()
db.session.add(User('test'))
db.session.commit()
if __name__ == '__main__':
app.run(debug=True)
索引模板,再次最小化:
<html>
<head>
</head>
<body>
<form method="post">
<input type="text" name="username"></input>
<input type="text" name="txt"></input>
<button type="submit">Submit</button>
<form>
</body>
</html>
我们可以使用app.initdb()创建一个数据库,然后启动应用程序并在表单中输入一些数据(用户名应为&#39; test&#39;)。一个新项目被插入到Thing表中。尼斯:)
然后我将模型移动到models.py:
from app import db
class Thing(db.Model):
...
class User(db.Model):
...
新的app.py看起来像:
import os
from flask import Flask, render_template, request
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SECRET_KEY'] = 'somesecret'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(app.instance_path, 'app.db')
db = SQLAlchemy(app)
#This line changes
import models
@app.route('/', methods=['GET', 'POST'])
def add():
if request.method == 'POST':
username = request.form['username']
text = request.form['txt']
# these 2 lines change: using models now
user = models.User.query.filter_by(username=username).first()
thing = models.Thing(user, text)
db.session.add(thing)
db.session.commit()
return render_template('index.html')
def initdb():
db.create_all()
db.session.add(User('test'))
db.session.commit()
if __name__ == '__main__':
app.run(debug=True)
现在发布表格会给我这个错误:
sqlalchemy.exc.InvalidRequestError
InvalidRequestError: Object '<Thing at 0x11111b950>' is already attached to session '1' (this is '2')
当我调试这个时,有趣的是用户被连接到与我想要添加的会话不同的会话。显然db导入会导致模型类的数据库会话出错?谁能向我解释这里发生了什么?
顺便说一句,我可以通过更改Thing类的 init 并分配user_id而不是user来解决这个问题。这样,Thing实例不会从User实例复制会话。但这并不能解释为什么User实例的会话开始不正确。
答案 0 :(得分:3)
您无意中导入了app.py
模块两次。这里发生了什么:
$ python path/to/app.py
__main__
的模块,并在其中执行app.py
。models
,然后导入app
。app
的模块,解释器创建一个名为app
的模块并在其中执行app.py
第二次 models.py
正在使用app.db
,但实际运行的烧瓶实例实际上正在使用__main__.db
。main_app.py
,只包含:
import app
if __name__ == '__main__':
app.app.run(debug=True)
并删除app.py中相应的if main子句。然后使用$ python path/to/main_app.py
运行您的应用。