我有一系列想要在称为粉丝的烧瓶蓝图中呈现的表单。 我在开发期间使用 sqlalchemy 到 SQLLite 来保存数据并使用 Flask-wtforms 进行渲染。 问题似乎出在 DecimalRangeField 上 - 如果我有两个或更多风扇并仅更改其中一个上的滑块,则另一个滑块似乎会移动以匹配它,尽管 DecimalRangeField 的数据值保持不变。 注意:下面的代码正在运行,当我在下面突出显示的重定向行被删除时,就会出现问题。
这是添加了重定向“修复”的routes.py代码:
@bp.route('/', methods=['GET', 'POST'])
def fans_index():
fans = Fan.query.all()
if fans.__len__() == 0:
return redirect(url_for('fans.newfan'))
form = FanForm(request.form)
if form.validate_on_submit(): # request.method == 'POST'
for fan in fans:
if fan.name == form.name.data:
fan.swtch = form.swtch.data
fan.speed = round(form.speed.data)
db.session.commit()
return redirect(url_for('fans.fans_index')) # <-- THIS is required, why?
else: # request.method == 'GET'
pass
forms = []
for fan in fans:
form = FanForm()
form.name.data = fan.name
form.swtch.data = fan.swtch
form.speed.data = fan.speed
forms.append(form)
return render_template('fans_index.html', title='Fans!', forms=forms)
这里是使用的表格:
class FanForm(FlaskForm):
name = HiddenField('Name')
swtch = BooleanField('Switch', render_kw={'class': 'swtch'})
speed = DecimalRangeField('Speed', render_kw={'class': 'speed'}, validators=[DataRequired()])
submit = SubmitField('Save Fan')
这是 html 模板:
<h1>Fans</h1>
<div class="container">
<div class="row">
{% for form in forms %}
<div class="col mx-1 shadow-5-strong border border-white rounded" style="max-width: 220px">
<h2 class="ms-1">{{ form.name.data }}:</h2>
<form class="mx-auto ms-3" name="{{ form.name.data }}" action="" method="post">
{{ form.hidden_tag() }}
<div>{{ form.name }}</div>
<p>
{{ form.speed.label }}: <span class="speed_display_val">{{ form.speed.data | round }}%</span><br>
{{ form.speed(min=20) }}<br>
{% for error in form.speed.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>
{{ form.swtch.label }} <span class="ms-3">{{ form.swtch }}</span><br>
{% for error in form.swtch.errors %}
<span style="color: red;">[{{ error }}]</span>
{% endfor %}
</p>
<p>{{ form.submit }}</p>
</form>
</div>
{% endfor %}
</div>
</div>
我还为此页面提供了一些简单的 JavaScript,用于为滑块设置动画,并在用户移动滑块或单击用于打开和关闭风扇的复选框时进行提交:
/* script to animate the slider value changing and post data on slider mouseup or switch click */
const values = Array.from(document.getElementsByClassName('speed_display_val'));
const speeds = Array.from(document.getElementsByClassName('speed'));
const swtches = Array.from(document.getElementsByClassName('swtch')); //Note: switch is a reserved word in JS
speeds.forEach((speed, i) => {
speed.oninput = (e) => { values[i].textContent = Math.round(e.target.value) + '%' };
speed.onmouseup = () => { speed.form.requestSubmit() };
});
swtches.forEach((swtch) => {
swtch.onclick = () => { swtch.form.requestSubmit() };
});
FlaskForm
将自动使用 flask.request.form
和 flask.request.files
中的值。要解决此问题,您可以传递 None
作为表单的 formdata
属性。这样,就不再需要重置 flask.request.form
的重定向了。
您的代码将如下所示。
@bp.route('/', methods=['GET', 'POST'])
def fans_index():
if Fan.query.count() == 0:
return redirect(url_for('.newfan'))
form = FanForm(request.form)
if form.validate_on_submit():
fan = Fan.query.filter_by(name=form.name.data).first()
fan.swtch = form.swtch.data
fan.speed = round(form.speed.data)
db.session.commit()
forms = [FanForm(formdata=None, obj=fan) for fan in Fan.query.all()]
return render_template('fans_index.html', **locals())