Ajouter un bouton d'annulation dans Flask avec Flask-WTF/WTForms

Aug 16 2020

Je voudrais ajouter un bouton d'annulation qui revient à la page précédente. Mon code est : 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')

et modèle de page :

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

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

J'ai une erreur 405 lorsque je clique sur le bouton Annuler : Méthode non autorisée.

Où est mon erreur ? et que dois-je ajouter pour revenir à la page précédente lorsque je clique sur Annuler ?

Merci

Réponses

baldy Sep 16 2020 at 10:12

Non, j'utilise TimeField pour forcer la capture d'une heure valide. Je n'ai pas essayé de changer cela en un champ de texte normal, j'ai donc opté pour l'option Annuler le lien ci-dessus à la place. Ma préférence est toujours d'avoir un bouton Annuler.

3 GreyLi Aug 17 2020 at 13:19

J'ai une erreur 405 lorsque je clique sur le bouton Annuler : Méthode non autorisée. Où est mon erreur ?

Lorsque vous soumettez le formulaire, les données seront envoyées sous forme de requête POST (car l'élément de formulaire rendu utilisera <form method="post">). Cependant, votre fonction d'affichage n'autorise que la requête GET par défaut, pour accepter la requête POST, vous devez spécifier le methodsparamètre comme ceci :

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

et que dois-je ajouter pour revenir à la page précédente lorsque je clique sur Annuler ?

Tout champ créé avec SubmitFieldsera affiché sous la forme d'un bouton de soumission ( <input type="submit">), il soumettra donc le formulaire lorsque vous cliquerez dessus.

Pour le faire revenir à la page précédente lorsque vous cliquez sur le bouton Annuler, il existe normalement deux méthodes pour y parvenir :

1. Attrapez le bouton Soumettre dans la fonction d'affichage

Comme la méthode dans la réponse de Ben . Vous pouvez simplement attraper la soumission puis rediriger l'utilisateur vers la page précédente :

@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 Puisque vous avez déjà défini novalidate=Truedans wtf.quick_form, vous n'avez pas besoin de définir render_kw={'formnovalidate': True}le cancelbouton dans la classe de formulaire.

2. Créez un <a>bouton au lieu d'un cancelchamp

Vous pouvez créer un <a>élément normal en tant que bouton d'annulation ( class="btn btn-secondary") et remplir le hrefparamètre avec l'URL de la page précédente (vous n'avez alors pas besoin d'ajouter de cancelchamp dans votre classe de formulaire). De cette façon, vous ne pouvez pas utiliser wtf.quick_form(), à la place vous devrez rendre chaque champ manuellement avec 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

Voici comment cela fonctionne pour moi.

Dans ma forme...

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

Dans mon code Python (views.py dans votre cas)...

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

Modification de dernière minute : la note de Gray Li ci-dessous concernant l'autorisation de votre fonction d'affichage à accepter les requêtes POST est également importante. Assurez-vous de le vérifier.