Flask SQLAlchemy 更新而不是插入
Flask SQLAlchely UPDATE instead of INSERT
我正在学习 Corey Schafer 制作 Flask Web 应用程序的教程系列,但我做错了。因此,当涉及到从用户向数据库创建新的 post 时,它会使用表单中的数据写入数据库,但是当我尝试从 添加另一个 post 时相同 用户我收到错误:
[SQL: UPDATE post SET user_id=? WHERE post.id = ?]
[parameters: (None, 1)]
我的 models.py
中有这个不应该让 user_id 成为 None
:
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
登录路径:
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('home'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user and bcrypt.check_password_hash(user.password, form.password.data):
login_user(user, remember=form.remember.data)
flash(f'Success.', category='success')
next_page = request.args.get('next')
return redirect(next_page) if next_page else redirect(url_for('home'))
else:
flash('Unsuccessful!', category='danger')
return render_template('login.html', title='Log In', form=form)
这是新增路线 post:
@app.route('/post/new', methods=['GET', 'POST'])
@login_required
def new_product():
form = PostForm()
if form.validate_on_submit():
post = Post(name=form.name.data, content=form.content.data, author=current_user)
db.session.add(post)
db.session.commit()
flash('Created!', category='success')
return redirect(url_for('home'))
return render_template('new.html', title='Add Post', form=form, legend='New Post')
这是表格:
class PostForm(FlaskForm):
name = StringField('Name', validators=[DataRequired()])
content = StringField('Content', validators=[DataRequired()])
在视频中,他制作了一个新的 post,但来自另一个用户帐户。我该如何逃脱?
整个错误是这样的:
127.0.0.1 - - [26/Apr/2021 15:00:34] "POST /post/new HTTP/1.1" 500 -
Traceback (most recent call last):
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\base.py", line 1705, in _execute_context
self.dialect.do_execute(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\default.py", line 716, in do_execute
cursor.execute(statement, parameters)
sqlite3.IntegrityError: NOT NULL constraint failed: post.user_id
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 2464, in __call__
return self.wsgi_app(environ, start_response)
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 2450, in wsgi_app
response = self.handle_exception(e)
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 1867, in handle_exception
reraise(exc_type, exc_value, tb)
File "D:\Python\HTML\venv\Lib\site-packages\flask\_compat.py", line 39, in reraise
raise value
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "D:\Python\HTML\venv\Lib\site-packages\flask\_compat.py", line 39, in reraise
raise value
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "D:\Python\HTML\blog\Lib\site-packages\flask_login\utils.py", line 272, in decorated_view
return func(*args, **kwargs)
File "D:\Python\HTML\store\routes.py", line 101, in new_product
db.session.commit()
File "<string>", line 2, in commit
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\session.py", line 1423, in commit
self._transaction.commit(_to_root=self.future)
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\session.py", line 829, in commit
self._prepare_impl()
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\session.py", line 808, in _prepare_impl
self.session.flush()
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\session.py", line 3255, in flush
self._flush(objects)
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\session.py", line 3395, in _flush
transaction.rollback(_capture_exception=True)
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\util\langhelpers.py", line 70, in __exit__
compat.raise_(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\util\compat.py", line 211, in raise_
raise exception
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\session.py", line 3355, in _flush
flush_context.execute()
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\unitofwork.py", line 453, in execute
rec.execute(self)
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\unitofwork.py", line 627, in execute
util.preloaded.orm_persistence.save_obj(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\persistence.py", line 234, in save_obj
_emit_update_statements(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\persistence.py", line 998, in _emit_update_statements
c = connection._execute_20(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\base.py", line 1520, in _execute_20
return meth(self, args_10style, kwargs_10style, execution_options)
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\sql\elements.py", line 313, in _execute_on_connection
return connection._execute_clauseelement(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\base.py", line 1389, in _execute_clauseelement
ret = self._execute_context(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\base.py", line 1748, in _execute_context
self._handle_dbapi_exception(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\base.py", line 1929, in _handle_dbapi_exception
util.raise_(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\util\compat.py", line 211, in raise_
raise exception
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\base.py", line 1705, in _execute_context
self.dialect.do_execute(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\default.py", line 716, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) NOT NULL constraint failed: post.user_id
[SQL: UPDATE post SET user_id=? WHERE post.id = ?]
[parameters: (None, 1)]
(Background on this error at: http://sqlalche.me/e/14/gkpj)
127.0.0.1 - - [26/Apr/2021 15:00:34] "GET /product/new?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 200 -
127.0.0.1 - - [26/Apr/2021 15:00:34] "GET /product/new?__debugger__=yes&cmd=resource&f=jquery.js HTTP/1.1" 200 -
127.0.0.1 - - [26/Apr/2021 15:00:34] "GET /product/new?__debugger__=yes&cmd=resource&f=debugger.js HTTP/1.1" 200 -
127.0.0.1 - - [26/Apr/2021 15:00:35] "GET /product/new?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 -
127.0.0.1 - - [26/Apr/2021 15:00:35] "GET /product/new?__debugger__=yes&cmd=resource&f=ubuntu.ttf HTTP/1.1" 200 -
127.0.0.1 - - [26/Apr/2021 15:00:35] "GET /product/new?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 -
解决方案:我在 forms.py
中弄乱了导入,就像这样:
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField, TextAreaField
from flask_wtf.file import FileField, FileAllowed
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
from store.models import User
from flask_login import current_user
必须重制为:
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from flask_login import current_user
from wtforms import StringField, PasswordField, SubmitField, BooleanField, TextAreaField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
from store.models import User
更新:感谢@IljaEverilä,我错了,backref
可以用于分配,而不仅仅是用于检索。我的回答解决了作者的问题,但我对教程代码错误的评论是不正确的,实际问题在另一个地方。有关 backref
的更多信息(带有赋值示例 - SQLAlchemy docs)
我把它放在那里是因为看起来提到的教程中的代码有错误。
问题是您没有通过任何 user_id
,但您通过了 author
。我检查了本教程中的代码,发现 author
字段存在于 Django 模型中,而不是 Flask 中。所以只需将 author=current_user
替换为 user_id=current_user.id
就可以了
我正在学习 Corey Schafer 制作 Flask Web 应用程序的教程系列,但我做错了。因此,当涉及到从用户向数据库创建新的 post 时,它会使用表单中的数据写入数据库,但是当我尝试从 添加另一个 post 时相同 用户我收到错误:
[SQL: UPDATE post SET user_id=? WHERE post.id = ?]
[parameters: (None, 1)]
我的 models.py
中有这个不应该让 user_id 成为 None
:
@login_manager.user_loader
def load_user(user_id):
return User.query.get(int(user_id))
登录路径:
@app.route('/login', methods=['GET', 'POST'])
def login():
if current_user.is_authenticated:
return redirect(url_for('home'))
form = LoginForm()
if form.validate_on_submit():
user = User.query.filter_by(username=form.username.data).first()
if user and bcrypt.check_password_hash(user.password, form.password.data):
login_user(user, remember=form.remember.data)
flash(f'Success.', category='success')
next_page = request.args.get('next')
return redirect(next_page) if next_page else redirect(url_for('home'))
else:
flash('Unsuccessful!', category='danger')
return render_template('login.html', title='Log In', form=form)
这是新增路线 post:
@app.route('/post/new', methods=['GET', 'POST'])
@login_required
def new_product():
form = PostForm()
if form.validate_on_submit():
post = Post(name=form.name.data, content=form.content.data, author=current_user)
db.session.add(post)
db.session.commit()
flash('Created!', category='success')
return redirect(url_for('home'))
return render_template('new.html', title='Add Post', form=form, legend='New Post')
这是表格:
class PostForm(FlaskForm):
name = StringField('Name', validators=[DataRequired()])
content = StringField('Content', validators=[DataRequired()])
在视频中,他制作了一个新的 post,但来自另一个用户帐户。我该如何逃脱?
整个错误是这样的:
127.0.0.1 - - [26/Apr/2021 15:00:34] "POST /post/new HTTP/1.1" 500 -
Traceback (most recent call last):
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\base.py", line 1705, in _execute_context
self.dialect.do_execute(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\default.py", line 716, in do_execute
cursor.execute(statement, parameters)
sqlite3.IntegrityError: NOT NULL constraint failed: post.user_id
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 2464, in __call__
return self.wsgi_app(environ, start_response)
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 2450, in wsgi_app
response = self.handle_exception(e)
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 1867, in handle_exception
reraise(exc_type, exc_value, tb)
File "D:\Python\HTML\venv\Lib\site-packages\flask\_compat.py", line 39, in reraise
raise value
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "D:\Python\HTML\venv\Lib\site-packages\flask\_compat.py", line 39, in reraise
raise value
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "D:\Python\HTML\venv\Lib\site-packages\flask\app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "D:\Python\HTML\blog\Lib\site-packages\flask_login\utils.py", line 272, in decorated_view
return func(*args, **kwargs)
File "D:\Python\HTML\store\routes.py", line 101, in new_product
db.session.commit()
File "<string>", line 2, in commit
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\session.py", line 1423, in commit
self._transaction.commit(_to_root=self.future)
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\session.py", line 829, in commit
self._prepare_impl()
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\session.py", line 808, in _prepare_impl
self.session.flush()
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\session.py", line 3255, in flush
self._flush(objects)
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\session.py", line 3395, in _flush
transaction.rollback(_capture_exception=True)
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\util\langhelpers.py", line 70, in __exit__
compat.raise_(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\util\compat.py", line 211, in raise_
raise exception
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\session.py", line 3355, in _flush
flush_context.execute()
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\unitofwork.py", line 453, in execute
rec.execute(self)
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\unitofwork.py", line 627, in execute
util.preloaded.orm_persistence.save_obj(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\persistence.py", line 234, in save_obj
_emit_update_statements(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\orm\persistence.py", line 998, in _emit_update_statements
c = connection._execute_20(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\base.py", line 1520, in _execute_20
return meth(self, args_10style, kwargs_10style, execution_options)
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\sql\elements.py", line 313, in _execute_on_connection
return connection._execute_clauseelement(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\base.py", line 1389, in _execute_clauseelement
ret = self._execute_context(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\base.py", line 1748, in _execute_context
self._handle_dbapi_exception(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\base.py", line 1929, in _handle_dbapi_exception
util.raise_(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\util\compat.py", line 211, in raise_
raise exception
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\base.py", line 1705, in _execute_context
self.dialect.do_execute(
File "D:\Python\HTML\venv\Lib\site-packages\sqlalchemy\engine\default.py", line 716, in do_execute
cursor.execute(statement, parameters)
sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) NOT NULL constraint failed: post.user_id
[SQL: UPDATE post SET user_id=? WHERE post.id = ?]
[parameters: (None, 1)]
(Background on this error at: http://sqlalche.me/e/14/gkpj)
127.0.0.1 - - [26/Apr/2021 15:00:34] "GET /product/new?__debugger__=yes&cmd=resource&f=style.css HTTP/1.1" 200 -
127.0.0.1 - - [26/Apr/2021 15:00:34] "GET /product/new?__debugger__=yes&cmd=resource&f=jquery.js HTTP/1.1" 200 -
127.0.0.1 - - [26/Apr/2021 15:00:34] "GET /product/new?__debugger__=yes&cmd=resource&f=debugger.js HTTP/1.1" 200 -
127.0.0.1 - - [26/Apr/2021 15:00:35] "GET /product/new?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 -
127.0.0.1 - - [26/Apr/2021 15:00:35] "GET /product/new?__debugger__=yes&cmd=resource&f=ubuntu.ttf HTTP/1.1" 200 -
127.0.0.1 - - [26/Apr/2021 15:00:35] "GET /product/new?__debugger__=yes&cmd=resource&f=console.png HTTP/1.1" 200 -
解决方案:我在 forms.py
中弄乱了导入,就像这样:
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, BooleanField, TextAreaField
from flask_wtf.file import FileField, FileAllowed
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
from store.models import User
from flask_login import current_user
必须重制为:
from flask_wtf import FlaskForm
from flask_wtf.file import FileField, FileAllowed
from flask_login import current_user
from wtforms import StringField, PasswordField, SubmitField, BooleanField, TextAreaField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
from store.models import User
更新:感谢@IljaEverilä,我错了,backref
可以用于分配,而不仅仅是用于检索。我的回答解决了作者的问题,但我对教程代码错误的评论是不正确的,实际问题在另一个地方。有关 backref
的更多信息(带有赋值示例 - SQLAlchemy docs)
我把它放在那里是因为看起来提到的教程中的代码有错误。
问题是您没有通过任何 user_id
,但您通过了 author
。我检查了本教程中的代码,发现 author
字段存在于 Django 模型中,而不是 Flask 中。所以只需将 author=current_user
替换为 user_id=current_user.id
就可以了