Aggiungi un pulsante Annulla in Flask con Flask-WTF/WTForms

Aug 16 2020

Vorrei aggiungere un pulsante Annulla che torna alla pagina precedente. Il mio codice è: 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 pagina modello:

{% 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 %}

viste, 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)

Ho un errore 405 quando clicco sul pulsante Annulla: metodo non consentito.

Dov'è il mio errore? e cosa devo aggiungere per tornare alla pagina precedente quando clicco su Annulla?

Grazie

Risposte

baldy Sep 16 2020 at 10:12

No, sto usando TimeField per imporre l'acquisizione di un tempo valido. Non ho provato a cambiarlo in un normale campo di testo, quindi sono andato con l'opzione Annulla collegamento sopra invece. La mia preferenza è comunque quella di avere un pulsante Annulla.

3 GreyLi Aug 17 2020 at 13:19

Ho un errore 405 quando clicco sul pulsante Annulla: metodo non consentito. Dov'è il mio errore?

Quando invii il modulo, i dati verranno inviati come richiesta POST (poiché l'elemento del modulo visualizzato utilizzerà <form method="post">). Tuttavia, la tua funzione di visualizzazione consente solo la richiesta GET come impostazione predefinita, per accettare la richiesta POST, devi specificare il methodsparametro in questo modo:

@orgs.route('/organisations/org_new', methods=['GET', 'POST'])  # <--
@login_required
def org_new():
   # ...

e cosa devo aggiungere per tornare alla pagina precedente quando clicco su Annulla?

Qualsiasi campo creato con SubmitFieldverrà visualizzato come un pulsante di invio ( <input type="submit">), quindi invierà il modulo quando fai clic su di esso.

Per farlo tornare alla pagina precedente quando si fa clic sul pulsante Annulla, ci sono normalmente due metodi per ottenere ciò:

1. Cattura il pulsante invia nella funzione di visualizzazione

Come il metodo nella risposta di Ben . Puoi semplicemente catturare l'invio e reindirizzare l'utente alla pagina precedente:

@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 Poiché hai già impostato novalidate=True, wtf.quick_formnon è necessario impostare render_kw={'formnovalidate': True}il cancelpulsante nella classe del modulo.

2. Creare un <a>pulsante anziché un cancelcampo

Puoi creare un <a>elemento normale come pulsante di annullamento ( class="btn btn-secondary") e riempire il hrefparametro con l'URL della pagina precedente (quindi non è necessario aggiungere cancelil campo nella classe del modulo). In questo modo, non puoi utilizzare wtf.quick_form(), invece dovrai eseguire il rendering di ogni campo manualmente con 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>
3 Ben Aug 17 2020 at 08:06

Ecco come funziona per me.

Nella mia forma...

btn_cancel = SubmitField(label='Cancel',
                         render_kw={'formnovalidate': True})

Nel mio codice Python (views.py nel tuo caso)...

if request.method == 'POST':
    if form.btn_cancel.data:
        return redirect(url_for('data'))

Modifica dell'ultimo minuto: anche la nota di Gray Li di seguito su come consentire alla funzione di visualizzazione di accettare le richieste POST è importante. Assicurati di controllarlo.