iam*_*pal 57 forms flask flask-wtforms
我在同一页面上有多个表单,将发送请求发送到烧瓶中的同一个处理程序.
我正在使用wtforms生成表单.
确定提交哪种表单的最佳方法是什么?
我目前正在使用action="?form=oneform".我认为应该有一些更好的方法来实现同样的目标?
Ale*_*sen 56
我一直在使用两个烧瓶片段的组合.第一个为表单添加前缀,然后使用validate_on_submit()检查前缀.我还使用LouisRoché的模板来确定在表单中按下哪些按钮.
引用丹雅各布:
例:
form1 = FormA(prefix="form1")
form2 = FormB(prefix="form2")
form3 = FormC(prefix="form3")
Run Code Online (Sandbox Code Playgroud)
然后,添加隐藏字段(或只检查提交字段):
if form1.validate_on_submit() and form1.submit.data:
Run Code Online (Sandbox Code Playgroud)
引用LouisRoché的话:
我的模板中有:
<input type="submit" name="btn" value="Save">
<input type="submit" name="btn" value="Cancel">
Run Code Online (Sandbox Code Playgroud)
并找出我在views.py文件中通过服务器端的按钮:
if request.form['btn'] == 'Save':
something0
else:
something1
Run Code Online (Sandbox Code Playgroud)
Gre*_* Li 51
上面的解决方案有一个验证错误,当一个表单导致验证错误时,两个表单都显示错误消息.我改变了if解决这个问题的顺序.
首先,SubmitField使用不同的名称定义您的多个,如下所示:
class Form1(Form):
name = StringField('name')
submit1 = SubmitField('submit')
class Form2(Form):
name = StringField('name')
submit2 = SubmitField('submit')
....
Run Code Online (Sandbox Code Playgroud)
然后添加一个过滤器view.py:
....
form1 = Form1()
form2 = Form2()
....
if form1.submit1.data and form1.validate(): # notice the order
....
if form2.submit2.data and form2.validate(): # notice the order
....
Run Code Online (Sandbox Code Playgroud)
现在问题解决了.
如果您想深入了解它,请继续阅读.
这是validate_on_submit():
def validate_on_submit(self):
"""
Checks if form has been submitted and if so runs validate. This is
a shortcut, equivalent to ``form.is_submitted() and form.validate()``
"""
return self.is_submitted() and self.validate()
Run Code Online (Sandbox Code Playgroud)
这是is_submitted():
def is_submitted():
"""Consider the form submitted if there is an active request and
the method is ``POST``, ``PUT``, ``PATCH``, or ``DELETE``.
"""
return _is_submitted() # bool(request) and request.method in SUBMIT_METHODS
Run Code Online (Sandbox Code Playgroud)
当您调用时form.validate_on_submit(),无论单击哪个提交按钮,它都会检查HTTP方法是否提交了表单.所以上面的小技巧只是添加一个过滤器(检查提交是否有数据,即form1.submit1.data).
此外,我们更改了顺序if,因此当我们单击一个提交时,它只调用validate()此表单,防止两个表单的验证错误.
故事还没有结束.这是.data:
@property
def data(self):
return dict((name, f.data) for name, f in iteritems(self._fields))
Run Code Online (Sandbox Code Playgroud)
它返回带有字段名称(键)和字段数据(值)的字典,但是,我们的两个表单提交按钮具有相同的名称submit(键)!
当我们单击第一个提交按钮(在form1中)时,调用form1.submit1.data返回一个这样的dict:
temp = {'submit': True}
Run Code Online (Sandbox Code Playgroud)
毫无疑问,当我们打电话时if form1.submit.data:,它会回来True.
当我们点击第二个提交按钮(在form2中)时,调用首先在dict .data中if form1.submit.data:添加一个键值,然后通过添加另一个键值来调用,最后,dict会这样:if form2.submit.data:
temp = {'submit': False, 'submit': True}
Run Code Online (Sandbox Code Playgroud)
现在我们调用if form1.submit.data:它返回True,即使我们点击的提交按钮是form2.
这就是为什么我们需要SubmitField用不同的名称来定义这两个.顺便说一句,感谢阅读(到这里)!
还有另一种方法可以在一个页面上处理多个表单.您可以使用多个视图来处理表单.例如:
...
@app.route('/')
def index():
register_form = RegisterForm()
login_form = LoginForm()
return render_template('index.html', register_form=register_form, login_form=login_form)
@app.route('/register', methods=['POST'])
def register():
register_form = RegisterForm()
login_form = LoginForm()
if register_form.validate_on_submit():
... # handle the register form
# render the same template to pass the error message
# or pass `form.errors` with `flash()` or `session` then redirect to /
return render_template('index.html', register_form=register_form, login_form=login_form)
@app.route('/login', methods=['POST'])
def login():
register_form = RegisterForm()
login_form = LoginForm()
if login_form.validate_on_submit():
... # handle the login form
# render the same template to pass the error message
# or pass `form.errors` with `flash()` or `session` then redirect to /
return render_template('index.html', register_form=register_form, login_form=login_form)
Run Code Online (Sandbox Code Playgroud)
在模板(index.html)中,您需要呈现两个表单并将action属性设置为目标视图:
<h1>Register</h1>
<form action="{{ url_for('register') }}" method="post">
{{ register_form.username }}
{{ register_form.password }}
{{ register_form.email }}
</form>
<h1>Login</h1>
<form action="{{ url_for('login') }}" method="post">
{{ login_form.username }}
{{ login_form.password }}
</form>
Run Code Online (Sandbox Code Playgroud)
Hie*_*ieu 17
一种简单的方法是为不同的提交字段设置不同的名称.举个例子:
forms.py:
class Login(Form):
...
login = SubmitField('Login')
class Register(Form):
...
register = SubmitField('Register')
Run Code Online (Sandbox Code Playgroud)
views.py:
@main.route('/')
def index():
login_form = Login()
register_form = Register()
if login_form.validate_on_submit() and login_form.login.data:
print "Login form is submitted"
elif register_form.validate_on_submit() and register_form.register.data:
print "Register form is submitted"
...
Run Code Online (Sandbox Code Playgroud)
作为其他答案,我还为页面上的每个表单的每个提交按钮分配了一个唯一的名称。
然后,flask web 操作如下所示 - 请注意formdata和obj参数,这有助于相应地初始化/保留表单字段:
@bp.route('/do-stuff', methods=['GET', 'POST'])
def do_stuff():
result = None
form_1 = None
form_2 = None
form_3 = None
if "submit_1" in request.form:
form_1 = Form1()
result = do_1(form_1)
elif "submit_2" in request.form:
form_2 = Form2()
result = do_2(form_2)
elif "submit_3" in request.form:
form_3 = Form3()
result = do_3(form_3)
if result is not None:
return result
# Pre-populate not submitted forms with default data.
# For the submitted form, leave the fields as they were.
if form_1 is None:
form_1 = Form1(formdata=None, obj=...)
if form_2 is None:
form_2 = Form2(formdata=None, obj=...)
if form_3 is None:
form_3 = Form3(formdata=None, obj=...)
return render_template("page.html", f1=form_1, f2=form_2, f3=form_3)
def do_1(form):
if form.validate_on_submit():
flash("Success 1")
return redirect(url_for(".do-stuff"))
def do_2(form):
if form.validate_on_submit():
flash("Success 2")
return redirect(url_for(".do-stuff"))
def do_3(form):
if form.validate_on_submit():
flash("Success 3")
return redirect(url_for(".do-stuff"))
Run Code Online (Sandbox Code Playgroud)
小智 6
我没有使用过 WTForms,但无论如何应该可以工作。这是一个非常快速和简单的答案;您需要做的就是为提交按钮使用不同的值。然后你可以根据每个做不同的定义。
在index.html中:
<div>
<form action="{{ url_for('do_stuff')}}" method="POST">
<h1>Plus</h1>
<input type = "number" id = "add_num1" name = "add_num1" required><label>Number 1</label><br>
<input type = "number" id = "add_num2" name = "add_num2" required><label>Number 2</label><br>
<input type = "submit" value = "submit_add" name = "submit" ><br>
</form>
<p>Answer: {{ add }}</p>
</div>
<div>
<form action="{{ url_for('do_stuff')}}" method="POST">
<h1>Minus</h1>
<input type = "number" id = "min_num1" name = "min_num1" required><label>Number 1</label><br>
<input type = "number" id = "min_num2" name = "min_num2" required><label>Number 2</label><br>
<input type = "submit" value = "submit_min" name = "submit"><br>
</form>
<p>Answer: {{ minus }}</p>
</div>
Run Code Online (Sandbox Code Playgroud)
在app.py中:
@app.route('/',methods=["POST"])
def do_stuff():
if request.method == 'POST':
add = ""
minus = ""
if request.form['submit'] == 'submit_add':
num1 = request.form['add_num1']
num2 = request.form['add_num2']
add = int(num1) + int(num2)
if request.form['submit'] == 'submit_min':
num1 = request.form['min_num1']
num2 = request.form['min_num2']
minus = int(num1) - int(num2)
return render_template('index.html', add = add, minus = minus)
Run Code Online (Sandbox Code Playgroud)
那么这里有一个简单的技巧
假设你有
表格 1、表格 2 和索引
Form1 <form method="post" action="{{ url_for('index',formid=1) }}">
Form2 <form method="post" action="{{ url_for('index',formid=2) }}">
Run Code Online (Sandbox Code Playgroud)
现在在索引中
@bp.route('/index', methods=['GET', 'POST'])
def index():
formid = request.args.get('formid', 1, type=int)
if formremote.validate_on_submit() and formid== 1:
return "Form One"
if form.validate_on_submit() and formid== 2:
return "Form Two"
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
44001 次 |
| 最近记录: |