write_code242
write_code242

Reputation: 1

Is there a reason why I'm getting a BadRequestKeyError when retrieving POST data from a form?

Hello this is a flask app and I'm unable to insert into the database using this code and template.

The error I am receiving is

2020-08-11 02:15:17,851: werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.

flask_app.py:

@app.route('/submission', methods=['GET', 'POST'])
def do_submission() -> 'html':

    @copy_current_request_context
    def log_request(req: 'flask_request', res: str) -> None:
        sleep(1)
        with UseDatabase(app.config['dbconfig']) as cursor:
            _SQL = """insert into client
                    (email, phonenumber)
                    values
                    (%s, %s)"""
            cursor.execute(_SQL, (req.form['useremail'],
                                 req.form['phone'],))

    results = ""
    try:
        t = Thread(target=log_request, args=(request, results))
        t.start()
    except Exception as err:
        print('***** Logging failed with this error:', str(err))
    return render_template('index.html',)

index.html:

  <form method='POST' action='/submission'>
  <table>
  <p>Use this form to submit a search request:</p>
  <tr><td>Email:</td><td><input name='useremail' type='EMAIL' width='60'></td></tr>
  <tr><td>Phone number:</td><td><input name='phone' type='TEXT' value='12505555555'></td></tr>
  </table>
  <p>When you're ready, click this button:</p>
  <p><input value='Do it!' type='SUBMIT'></p>
  </form>

DBcm.py

I suppose I should have added this code too. Here is the missing code below: I really can't figure out why this isn't working. It seems like it is totally ok.

# Context manager for connecting/disconnecting to a database.

import mysql.connector

class SQLError(Exception):
    """Raised if the query caused problems."""
    pass


class UseDatabase:
    def __init__(self, config: dict):
        self.configuration = config

    def __enter__(self) -> 'cursor':

        try:
            self.conn = mysql.connector.connect(**self.configuration)
            self.cursor = self.conn.cursor()
            return self.cursor
        except mysql.connector.errors.InterfaceError as err:
            raise ConnectionError(err) from err
        except mysql.connector.errors.ProgrammingError as err:
            raise CredentialsError(err) from err

    def __exit__(self, exc_type, exc_value, exc_traceback):
        self.conn.commit()
        self.cursor.close()
        self.conn.close()
        if exc_type is mysql.connector.errors.ProgrammingError:
            raise SQLError(exc_value)
        elif exc_type:
            raise exc_type(exc_value)

Upvotes: 0

Views: 82

Answers (2)

BlackList96
BlackList96

Reputation: 449

What does the error mean?

See, there is the word BadRequestKeyError which means that you are trying to access data using a key that doesn't exist.

Why this error?

This error happens generally when there is a mismatch between the names you have provided in the input fields and the names using which you are trying to get the values from the request object. In your case, when you are starting the server and when the log_request method is called, you are trying to access useremail and phone from an empty request object as no POST request happened yet. As the request object is empty, so these keys don't exist.

How to solve this error?

So, we need to check if the request object is empty or not. Now, the request object might be empty, but make sure that the log_request method gets called only when there is POST request. There are different edge cases which you need to handle but I am assuming that the request object will not be empty if it is coming as POST request.

@app.route('/submission', methods=['GET', 'POST'])
def do_submission() -> 'html':

    if request.method == 'POST':

        @copy_current_request_context
        def log_request(req: 'flask_request', res: str) -> None:
            sleep(1)
            with UseDatabase(app.config['dbconfig']) as cursor:
                _SQL = """insert into client
                        (email, phonenumber)
                        values
                        (%s, %s)"""
                cursor.execute(_SQL, (req.form['useremail'],
                                    req.form['phone']))
                # rest of the logic

        results = ""
        try:
            t = Thread(target=log_request, args=(request, results))
            t.start()
        except Exception as err:
            print('***** Logging failed with this error:', str(err))

    else:

        return render_template('index.html')

Recommendation

However, I will highly recommend you not to use Thread for such a simple application. It is too much overkill for a simple task.

Upvotes: 1

write_code242
write_code242

Reputation: 1

@BlackList96

After reading your answer and your advice I tested the following and it worked! Thank you for helping me out:

@app.route('/submission', methods=['POST'])
def do_submission() -> 'html':

    if request.method == 'POST':

        @copy_current_request_context
        def log_request(req: 'flask_request', res: str) -> None:
            sleep(15)
            with UseDatabase(app.config['dbconfig']) as cursor:
                _SQL = """insert into client
                        (email, phonenumber)
                        values
                        (%s, %s)"""
                cursor.execute(_SQL, (req.form['useremail'],
                                    req.form['phone'],))
        results = ""
        log_request(request,results)
    return render_template('index.html')

Upvotes: 0

Related Questions