В приведенном выше решении есть ошибка проверки, когда одна из форм вызывает ошибку проверки, обе формы отображают сообщение об ошибке. Я изменяю порядок if
, чтобы решить эту проблему.
Сначала определите несколько SubmitField
с разными именами, например:
class Form1(Form):
name = StringField('name')
submit1 = SubmitField('submit')
class Form2(Form):
name = StringField('name')
submit2 = SubmitField('submit')
....
Затем добавьте фильтр в 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
....
Теперь проблема решена.
Если вы хотите погрузиться в него, продолжайте читать.
Здесь 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()
И вот 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
Когда вы вызываете form.validate_on_submit()
, он проверяет, была ли форма передана методом HTTP, независимо от того, какая кнопка отправки нажата. Таким образом, маленький трюк выше - это просто добавить фильтр (чтобы проверить, есть ли у submit данные, т. Е. form1.submit1.data
).
Кроме того, мы меняем порядок if
, поэтому, когда мы нажимаем кнопку submit, он вызывает только эту validate()
, предотвращая ошибку проверки для обеих форм.
История еще не закончена. Вот .data
:
@property
def data(self):
return dict((name, f.data) for name, f in iteritems(self._fields))
Он возвращает dict с именем поля (ключ) и данными поля (значение), однако наша кнопка отправки формы имеет то же имя submit
(ключ)!
Когда мы щелкаем по первой кнопке отправки (в форме1), вызов из form1.submit1.data
возвращает a dict следующим образом:
temp = {'submit': True}
Нет никаких сомнений, когда мы вызываем if form1.submit.data:
, он возвращает True
.
Когда мы нажимаем вторую кнопку отправки (в форме2), вызов .data
в if form1.submit.data:
сначала добавляет значение ключа в dict, а затем вызов из if form2.submit.data:
добавьте еще одно значение ключа, в конце концов, dict будет так:
temp = {'submit': False, 'submit': True}
Теперь мы вызываем if form1.submit.data:
, он возвращает True
, даже если кнопка отправки, которую мы нажали, была в форме2.
Вот почему нам нужно определить два 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)
В шаблоне (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>