flask-wtf recaptcha validation through ajax

时间:2018-06-04 16:50:13

标签: python ajax flask recaptcha flask-wtforms

Today I was solving how to use recaptcha from flask-WTF 0.14.2 in form which is POST on server via ajax. I wasn't able to find solution how to implement recaptcha with ajax and successfully validate it on server and then send answer back to client. Recaptcha validation was complaining with this error despite I was sending required "response parameter" from client to server:

'recaptcha': ['The response parameter is missing.']

I was not able to find answer anywhere on Stackoverflow so I post here my own working code.

1 个答案:

答案 0 :(得分:1)

Here is my Flask code:

from flask_wtf import FlaskForm, RecaptchaField
from wtforms import StringField, TextAreaField
from wtforms.validators import InputRequired, Email, Length, Optional


#Google keys
app.config['RECAPTCHA_PUBLIC_KEY'] = 'my_public_key'
app.config['RECAPTCHA_PRIVATE_KEY'] = 'My_private_key'


# flask-WTF contact us form
class ContactUs(FlaskForm):
    name = StringField('name', validators=[InputRequired(), Length(max=50)])
    surname = StringField('surname', validators=[Optional(), Length(max=50)])
    email = StringField('email', validators=[InputRequired(), Length(max=100), Email(message='Invalid email')])
    message = TextAreaField('message', validators = [InputRequired(), Length(max=5000)])
    recaptcha = RecaptchaField()


@app.route ("/contact", methods=['GET','POST'])
def contact():
    form = ContactUs()
    if request.method =='POST':
        if form.validate_on_submit():
            #do something with validated data
            return jsonify(message = 'ok')            
        else:
            #send back form.errors to front-end            
            return jsonify(message = "error", data = form.errors)    

    return render_template("contact.html", form = form)

Here is simplified html template:

<label class="control-label">First name*</label>
{{ form.name }}
<label class="control-label">Last name</label>
{{ form.surname }}
<label class="control-label">Email address*</label>
{{ form.email }}
<label class="control-label">Your message*</label>
{{ form.message }}
{{ form.recaptcha }}
<button type="button" class="btn btn-primary" onclick="SendMessage()">Send Message</button>

And finally here is AJAX part:

function SendMessage(){
    var url = "{{url_for('contact')}}"
    var name = document.getElementById('name').value
    var surname = document.getElementById('surname').value
    var email = document.getElementById('email').value
    var message = document.getElementById('message').value

    var formData = new FormData()
    formData.append('name', name.value)
    formData.append('surname', surname.value)
    formData.append('email', email.value)
    formData.append('message', message.value)
    formData.append('g-recaptcha-response', grecaptcha.getResponse()) 
    //from flask-wtf library I learnt that recaptcha is awaiting 'g-recaptcha-response' in FormData

    $.ajax({
    type: 'POST',
    url: url,
    data: formData,
    processData: false,
    contentType: false,
    success: function(response){
            grecaptcha.reset() //recaptcha reset
            if(response.message == 'ok'){
                console.log('got ok')                   
            }
            if(response.message == 'error'){
                //handle flask-wtf errors here
            }}, 
    error: function(response){
            grecaptcha.reset() 
            console.log('got error')                
            }
    })}

I hope it can help somebody who is looking up recaptcha validation with flask-wtf and ajax.