В приведенном выше решении есть ошибка проверки: когда одна форма вызывает ошибку проверки, в обеих формах отображается сообщение об ошибке. Я меняю порядок 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
, поэтому, когда мы нажимаем на одну отправку, она вызывает только validate()
эту форму, предотвращая ошибку проверки для обеих форм.
История еще не закончена. Вот .data
:
@property
def data(self):
return dict((name, f.data) for name, f in iteritems(self._fields))
Он возвращает dict с именем поля (ключ) и данными поля (значение), однако наши две кнопки отправки формы имеют то же имя submit
(ключ)!
Когда мы нажимаем первую кнопку отправки (в form1), вызов из form1.submit1.data
возвращает такой dict:
temp = {'submit': True}
Несомненно, когда мы вызываем if form1.submit.data:
, он возвращает True
.
Когда мы нажимаем вторую кнопку отправки (в form2), вызов .data
в if form1.submit.data:
добавляет пару "ключ-значение" в dict first, затем вызов 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>
person
Grey Li
schedule
29.09.2016