Adicione um botão cancelar no Flask com Flask-WTF/WTForms
Eu gostaria de adicionar um botão de cancelamento que volta para a página anterior. Meu código é: forms.py:
from flask_wtf import Form
from wtforms import StringField, HiddenField, SubmitField
from wtforms.validators import DataRequired, Length, ValidationError
def _required(form, field):
if not field.raw_data or not field.raw_data[0]:
raise ValidationError('Field is required')
class OrganisationForm(Form):
id = HiddenField('id', default="-1")
name = StringField('name', validators=[DataRequired()])
manager_name = StringField('manager_name')
address = StringField('address', validators=[DataRequired()])
city = StringField('city', validators=[DataRequired()])
postal_code = StringField('postal_code', validators=[DataRequired(), Length(max=16)])
province = StringField('province', validators=[Length(max=2, message="Can't exceed 2 characters")])
country = StringField('country', validators=[DataRequired()])
submit = SubmitField('Add')
cancel = SubmitField('Cancel')
e página de modelo:
{% block content %}
<div class="content-section">
{{ utils.flashed_messages() }}
<div class="center">
{% if add_orgnisation %}
<h1>add an organisation</h1>
{% else %}
<h1>Edit an organisation</h1>
{% endif %}
<br/>
<br/>
{{ wtf.quick_form(form,novalidate=True) }}
</div>
</div>
{% endblock %}
visualizações,py
@orgs.route('/organisations/org_new')
@login_required
def org_new():
add_orgnisation = True
form = OrganisationForm()
return render_template("organisations/organisation_form.html", form=form, title="New Organisation", edit=False, add_orgnisation=add_orgnisation)
Eu tenho um erro 405 quando clico no botão cancelar: Método não permitido.
Onde está o meu erro? e o que devo adicionar para voltar à página anterior quando clico em Cancelar?
obrigado
Respostas
Não, estou usando o TimeField para forçar a captura de um Time válido. Eu não tentei mudar isso para um campo de texto normal, então optei pela opção Cancelar link acima. Minha preferência ainda é ter um botão Cancelar.
Eu tenho um erro 405 quando clico no botão cancelar: Método não permitido. Onde está o meu erro?
Ao enviar o formulário, os dados serão enviados como uma solicitação POST (porque o elemento do formulário renderizado usará <form method="post">
). No entanto, sua função de exibição permite apenas a solicitação GET como padrão, para aceitar a solicitação POST, você deve especificar o methods
parâmetro como este:
@orgs.route('/organisations/org_new', methods=['GET', 'POST']) # <--
@login_required
def org_new():
# ...
e o que devo adicionar para voltar à página anterior quando clico em Cancelar?
Qualquer campo criado com SubmitField
será renderizado como um botão de envio ( <input type="submit">
), portanto, enviará o formulário quando você clicar nele.
Para voltar à página anterior ao clicar no botão Cancelar, normalmente existem dois métodos para fazer isso:
1. Pegue o botão enviar na função de visualização
Como o método na resposta de Ben . Você pode simplesmente capturar o envio e redirecionar o usuário para a página anterior:
@orgs.route('/organisations/org_new', methods=['GET', 'POST'])
@login_required
def org_new():
if request.method == 'POST':
if form.cancel.data: # if cancel button is clicked, the form.cancel.data will be True
return redirect(url_for('previous_page_view_name'))
# ...
PS Como você já definiu novalidate=True
, wtf.quick_form
não precisa definir render_kw={'formnovalidate': True}
o cancel
botão na classe de formulário.
2. Crie um <a>
botão em vez de um cancel
campo
Você pode criar um <a>
elemento normal como botão cancelar ( class="btn btn-secondary"
) e preencher o href
parâmetro com a URL da página anterior (assim você não precisa adicionar cancel
campo na sua classe de formulário). Dessa forma, você não pode usar wtf.quick_form()
, em vez disso, precisará renderizar cada campo manualmente com wtf.form_field()
:
<form method="post">
{{ wtf.form_field(form.id) }}
{{ wtf.form_field(form.name) }}
{{ wtf.form_field(form.manager_name) }}
{{ wtf.form_field(form.address) }}
...
{{ wtf.form_field(form.submit) }}
<a href="{{ url_for('previous_page_view_name') }}" class="btn btn-secondary">Cancel</a>
</form>
Veja como isso funciona para mim.
Na minha forma...
btn_cancel = SubmitField(label='Cancel',
render_kw={'formnovalidate': True})
No meu código Python (views.py no seu caso)...
if request.method == 'POST':
if form.btn_cancel.data:
return redirect(url_for('data'))
Edição de última hora: a observação de Gray Li abaixo sobre permitir que sua função de exibição aceite solicitações POST também é importante. Certifique-se de verificar.