Вопрос

I am trying to combine WTForms with jQuery Form Plugin. With the latter, I bind a form and provide a callback function. On the other hand, WTForms has to do the validation job on the server side.

My problem is: when form.validate() yields False, no error is displayed.

My question: How is it possible, for such a situation where WTForms is coupled with JQuery, to ask for validation from server side and, in case validation fails, display error message ?

I think library wtforms-parsleyjs would have been a good option, but not all WTForms fields are supported (such as FormField which is not).

Probably this question contains the answer, but not enough details for me to go further.

Thanks in advance for any hint.

Here my Flask View:

@app.route('/test', methods=['GET', 'POST'])
def get_form():
        form = BForm(request.form)
        D=form.uu.entries
        if request.method == 'POST' and form.validate():
            cl1=[]
            for entry in D:
                cl1.append(entry.ff.data)
            a=0
            for L, v in enumerate(cl1):
                a+=v
            jresult={"result":float(a)}
            return jsonify(jresult)
        return render_template('test.html', form=form)

Here the Form

field = DecimalField(default=0.0, validators=[NumberRange(min=0, max=2)])
text = TextField()

class AForm(Form):
    ff=field
    tt=text

class BForm(Form):
    uu=FieldList(FormField(AForm), min_entries=2)

Here the template

<script type=text/javascript>
    $(document).ready(function() {
        $("#result").html('?');
        // bind 'myForm' and provide a simple callback function 
        $('#myForm').ajaxForm(function(response) {
            restxt=$('#result').html(response.result) 
        });
    });
</script>

<form action="/test" id="myForm" method=post>
        {% for field in form.uu %}
            {{ render_field(field.ff) }}
        {% endfor %}        
    <input class="button" type="submit" value="calc">
    <span id="result">?</span>
</form>

UPDATE: following @Miguel comment, here the render_field macro:

{% macro render_field(field) %}
  {{ field(class_='form-control', **kwargs)|safe }}
  {% if field.errors %}
    {% for error in field.errors %}
      <span style="color: black;"> {{error}} </span>
    {% endfor %}
  {% endif %}
{% endmacro %}
Это было полезно?

Решение

I have described a general implementation for validating ajax forms in this answer. This was in the context of validating form fields as they are being entered (i.e. prior to form submission), but the same idea applies when the form is finally submitted.

Your render_field() macro is written to render field errors server-side. But your POST request does not re-render the form, it just returns the result of a calculation. You really never give a chance to the server to re-render or update the form.

The easiest solution is to not use ajax for the form submission. Then when you get a POST request you validate, and return a new page back to the client. To render that page you will pass the form (which will have any validation errors in it) and the result of your calculation.

If you want to continue with ajax submission then you need to figure out a strategy to update the form in the client. Here are some ideas:

  • your JSON response must include any validation errors, so you will need to copy them from the form object into the JSON dictionary.
  • your ajax success handler not only needs to update the HTML of #result but also needs to insert any validation errors into the DOM in the proper place.
  • your render_field() macro cannot render error messages because at the time this macro runs the errors are not known yet. Instead you should just create empty and invisible elements that can hold the errors, and these will be populated by the client in the ajax submission callback.

I hope this helps.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top