gpt4 book ai didi

Flask-sqlalchemy:移动模型导致 InvalidRequestError - 已附加到 session

转载 作者:行者123 更新时间:2023-12-03 17:18:57 24 4
gpt4 key购买 nike

将我的模型移动到它们自己的模块会导致 InvalidRequestError.. 这似乎与数据库 session 以及我在模型模块中导入数据库的方式有关。

我试图将这个问题减少到所需的最少代码量。首先,一个工作 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()创建一个数据库,然后启动应用程序并在表单中输入一些数据(用户名应该是“test”)。新项目将插入到事物表中。不错:)

但随后我将模型移至 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')

当我调试此问题时,有趣的是,用户附加到的 session 与我尝试添加的 session 不同。那么显然数据库导入会导致模型类的数据库 session 出现问题?谁能向我解释一下这里发生了什么?

顺便说一句,我可以通过更改 Thing 类的 init 并分配 user_id 而不是 user 来解决此问题。这样,事物实例就不会从用户实例复制 session 。但这并不能解释为什么 User 实例一开始就有一个不正确的 session 。

最佳答案

您无意中导入了 app.py 模块两次。发生的情况如下:

  • 您输入$ python path/to/app.py
  • 解释器创建一个名为__main__的模块,并在其中执行app.py
  • 您导入模型,模型又导入应用
  • 没有名为 app 的模块,解释器创建一个名为 app 的模块,并在其中执行 app.py时间
  • 您的models.py正在使用app.db,但实际运行的flask实例实际上正在使用__main__.db。<

修复此问题的最佳方法是添加第三个模块,以便可以将其称为 main,例如 main_app.py,其中仅包含:

import app
if __name__ == '__main__':
app.app.run(debug=True)

并删除app.py中相应的if主子句。然后使用 $ python path/to/main_app.py 运行您的应用程序。

关于Flask-sqlalchemy:移动模型导致 InvalidRequestError - 已附加到 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24697394/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com