Home > Software design >  Variables getting refreshed with HTML POST operation in Flask
Variables getting refreshed with HTML POST operation in Flask

Time:04-08

I am trying to build a simple numeric captcha for my contact page in Flask. The contact page end-point loads in GET mode and initializes the values of the captcha verification. When I submit the form in POST mode, I expect my user-entered form value to match the captcha value. However, it is not working as expected. I did some troubleshooting with print statements to see how the values are changing and it appears that the captcha variables are getting re-initialised with the POST operation. Can someone please suggest a workaround? My Python code is shared below:

@bp.route('/contact/', methods=('GET', 'POST'))
def contact():
    # Initialize captcha values
    cap_a = random.randint(0, 9)
    cap_b = random.randint(0, 9)
    cap_prod = cap_a * cap_b
    print(cap_a, cap_b, cap_prod)
    if request.method == "POST":
        error = None
        log_file = current_app.config['LOGFILE']
        full_name = request.form['fullname']
        email_addr = request.form['email']
        phone_no = request.form['phone']
        msg_body = request.form['message']
        num_prod = request.form['verifycaptcha']
        print(cap_a, cap_b, cap_prod)
        print(full_name, email_addr, phone_no, msg_body, num_prod)
        if not full_name:
            error = 'Full name is required.'
        elif not email_addr:
            error = 'Email address is required.'
        elif not msg_body:
            error = 'Message body is required.'
        if num_prod != cap_prod:
            error = 'Incorrect captcha verification.'
        if error is None:
            # Perform some operations
            pass
            try:
                with current_app.app_context():
                    mail = Mail()
                    mail.init_app(current_app)
                    mail.send(msg)
                    error = 'Mail sent successfully!'
            except:
                error = 'Mail engine error encountered. Please retry after some time.'
                f = open(log_file, "a")
                f.write('[' datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') '] ' error '\n')
                f.close()
        flash(error)
    return render_template('contact.html',num_a = cap_a, num_b = cap_b)

CodePudding user response:

cap_a = random.randint(0, 9)
cap_b = random.randint(0, 9)
cap_prod = cap_a * cap_b

these are 2 random numbers and you are creating cap_prod. You are not saving the cap_prod anywhere. You are instead calculating it again when POST request comes (this time it will be 2 new random numbers)

You need to save the captcha that you created during the GET, and then when the POST comes , compare with the value that was originally sent.

If you are going to support refresh-captcha image in the future (you need to have an API call that will generate a new captcha and save it)

CodePudding user response:

I figured out the solution by storing the captcha variables in the session dictionary of Flask and checking for its existence before re-initialising the values.

def contact():
    # Initialize captcha values
    if 'product' not in session:
        cap_a = random.randint(0, 9)
        cap_b = random.randint(0, 9)
        session['captcha_a'] = cap_a
        session['captcha_b'] = cap_b
        session['product'] = cap_a * cap_b
    else:
        cap_a = session.get('captcha_a')
        cap_b = session.get('captcha_b')
    if request.method == "POST":
        pass
        # Rest of the code

Working examples of the above solution can be found at Fadmeter.com and FadURL.com.

  • Related