FlaskForm 必须重新加载 select 个选项
FlaskForm had to reload select choices
我是 Python 和 Flask 的新手。我正在尝试使用 WTForm FlaskForm,但在 SelectField 中的选择有问题。我正在像这样构建我的表格。
class FightForm(FlaskForm):
fight_id = StringField('fight_id', render_kw={'readonly': True})
fight_type_id = SelectField('fight_type_id',
choices=[(t.fight_type_id, t.type_name) for t in fight_type.query.all()], validate_choice=False, validators=[DataRequired()])
这些选择似乎只加载了 1 次。如果我去添加一个新的 fight_type
,我必须停止应用程序并重新启动它才能刷新。
另外,我找到了这个答案,,但是 FlaskForm 不会触发这个建议的 __init__
函数。
无论如何我临时将其更改为 Form 并收到错误消息说 fight_type_id 不属于 form(释义)。
我希望每次调用该页面时都刷新这些内容。
我认为你应该看看 WTForms-SQLAlchemy 扩展。
QuerySelectField 根据提交的数据库查询动态加载所有数据库条目。可以为条目的标签定义一列。提交表单时,自动从数据库中查询选中的对象,通过字段返回。
烧瓶 (app.py)
from flask import (
Flask,
redirect,
render_template,
request,
url_for
)
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from flask_wtf.csrf import CSRFProtect
from wtforms.validators import InputRequired
from wtforms_sqlalchemy.fields import QuerySelectField
app = Flask(__name__)
app.secret_key = b'your secret here'
db = SQLAlchemy(app)
csrf = CSRFProtect(app)
class FightType(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False, unique=True)
class Fight(db.Model):
id = db.Column(db.Integer, primary_key=True)
type_id = db.Column(db.Integer, db.ForeignKey('fight_type.id'))
type = db.relationship('FightType', backref='fights')
class FightForm(FlaskForm):
type = QuerySelectField(
get_label='name',
query_factory=lambda: FightType.query.all(),
validators=[InputRequired()]
)
with app.app_context():
db.drop_all()
db.create_all()
types = [FightType(name=f'type-{i}') for i in range(10)]
db.session.add_all(types)
db.session.commit()
@app.route('/')
def index():
fights = Fight.query.all()
return render_template('index.html', **locals())
@app.route('/fight/new', methods=['GET', 'POST'])
def fight_create():
form = FightForm(request.form)
if form.validate_on_submit():
fight = Fight()
form.populate_obj(fight)
db.session.add(fight)
db.session.commit()
return redirect(url_for('index'))
return render_template('create.html', **locals())
@app.route('/fight/<int:fight_id>/edit', methods=['GET', 'POST'])
def fight_update(fight_id):
fight = Fight.query.get_or_404(fight_id)
form = FightForm(request.form, obj=fight)
if form.validate_on_submit():
form.populate_obj(fight)
db.session.commit()
return redirect(url_for('index'))
return render_template('update.html', **locals())
HTML (templated/index.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Index</title>
</head>
<body>
<a href="{{ url_for('fight_create') }}">New</a>
<ul>
{% for f in fights -%}
<li>
<a href="{{ url_for('fight_update', fight_id=f.id) }}">
{{ f.id }} - {{ f.type.name }}
</a>
</li>
{% endfor -%}
</ul>
</body>
</html>
HTML (templates/create.html, templates/update.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Fight</title>
</head>
<body>
<form method="post">
{{ form.csrf_token }}
{{ form.type.label }} {{ form.type() }}
<input type="submit" value="Go">
</form>
</body>
</html>
我是 Python 和 Flask 的新手。我正在尝试使用 WTForm FlaskForm,但在 SelectField 中的选择有问题。我正在像这样构建我的表格。
class FightForm(FlaskForm):
fight_id = StringField('fight_id', render_kw={'readonly': True})
fight_type_id = SelectField('fight_type_id',
choices=[(t.fight_type_id, t.type_name) for t in fight_type.query.all()], validate_choice=False, validators=[DataRequired()])
这些选择似乎只加载了 1 次。如果我去添加一个新的 fight_type
,我必须停止应用程序并重新启动它才能刷新。
另外,我找到了这个答案,__init__
函数。
无论如何我临时将其更改为 Form 并收到错误消息说 fight_type_id 不属于 form(释义)。
我希望每次调用该页面时都刷新这些内容。
我认为你应该看看 WTForms-SQLAlchemy 扩展。
QuerySelectField 根据提交的数据库查询动态加载所有数据库条目。可以为条目的标签定义一列。提交表单时,自动从数据库中查询选中的对象,通过字段返回。
烧瓶 (app.py)
from flask import (
Flask,
redirect,
render_template,
request,
url_for
)
from flask_sqlalchemy import SQLAlchemy
from flask_wtf import FlaskForm
from flask_wtf.csrf import CSRFProtect
from wtforms.validators import InputRequired
from wtforms_sqlalchemy.fields import QuerySelectField
app = Flask(__name__)
app.secret_key = b'your secret here'
db = SQLAlchemy(app)
csrf = CSRFProtect(app)
class FightType(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String, nullable=False, unique=True)
class Fight(db.Model):
id = db.Column(db.Integer, primary_key=True)
type_id = db.Column(db.Integer, db.ForeignKey('fight_type.id'))
type = db.relationship('FightType', backref='fights')
class FightForm(FlaskForm):
type = QuerySelectField(
get_label='name',
query_factory=lambda: FightType.query.all(),
validators=[InputRequired()]
)
with app.app_context():
db.drop_all()
db.create_all()
types = [FightType(name=f'type-{i}') for i in range(10)]
db.session.add_all(types)
db.session.commit()
@app.route('/')
def index():
fights = Fight.query.all()
return render_template('index.html', **locals())
@app.route('/fight/new', methods=['GET', 'POST'])
def fight_create():
form = FightForm(request.form)
if form.validate_on_submit():
fight = Fight()
form.populate_obj(fight)
db.session.add(fight)
db.session.commit()
return redirect(url_for('index'))
return render_template('create.html', **locals())
@app.route('/fight/<int:fight_id>/edit', methods=['GET', 'POST'])
def fight_update(fight_id):
fight = Fight.query.get_or_404(fight_id)
form = FightForm(request.form, obj=fight)
if form.validate_on_submit():
form.populate_obj(fight)
db.session.commit()
return redirect(url_for('index'))
return render_template('update.html', **locals())
HTML (templated/index.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Index</title>
</head>
<body>
<a href="{{ url_for('fight_create') }}">New</a>
<ul>
{% for f in fights -%}
<li>
<a href="{{ url_for('fight_update', fight_id=f.id) }}">
{{ f.id }} - {{ f.type.name }}
</a>
</li>
{% endfor -%}
</ul>
</body>
</html>
HTML (templates/create.html, templates/update.html)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Fight</title>
</head>
<body>
<form method="post">
{{ form.csrf_token }}
{{ form.type.label }} {{ form.type() }}
<input type="submit" value="Go">
</form>
</body>
</html>