Question

Can't submit WTForms data into MySQL database because the data submitted is still in Unbound Fields and stuff, although I attempted to convert it into a string. Not sure what to do.

I am trying to create a registration form using Flask and WTForms. I am getting the following error when I get to the part of putting the data (username, password, email) into the MySQL database:

I have tried looking everywhere but there is no where that explains how I could fix this. The following is the relevant code:

class User():
global cur
cur = config.conn.cursor()

def __init__(self, username, password, email):
    self.usr = username
    self.pwd = password
    self.mail = email

def database(self, username, password, email):
    u_p_e = cur.execute("INSERT into users (username, pwd, e-mail) VALUES ('%s', '%s', '%s')"
                                                               % (username, password, email))
    cur.commit()


class Register(Form):
    reg_username = TextField('Username', [validators.Length(min=1, max = 12)])
    username = str(reg_username)
    reg_password = PasswordField('Password', [
             validators.Required(),
             validators.EqualTo('confirm_password', message='Passwords do not match')
    ])

    confirm_password = PasswordField('Confirm Password')
    password = str(confirm_password)
    reg_email = TextField('Email', [validators.Length(min=6, max=35)])
    email = str(reg_email)

    enter_db = User(username, password, email)
    enter_db.database(username, password, email)

I am new to web development using Flask/WTForms.

Was it helpful?

Solution

There are two problems with your code.

The first problem is with how you define your class.

class Register(Form):
    reg_username = TextField('Username', [validators.Length(min=1, max = 12)])
    username = str(reg_username)
    reg_password = PasswordField('Password', [
             validators.Required(),
             validators.EqualTo('confirm_password', message='Passwords do not match')
    ])

    confirm_password = PasswordField('Confirm Password')
    password = str(confirm_password)
    reg_email = TextField('Email', [validators.Length(min=6, max=35)])
    email = str(reg_email)

    enter_db = User(username, password, email)
    enter_db.database(username, password, email)

Your calls to str happen when the class is created and convert the reg_username, confirm_password, and reg_email attributes to strings. The value you are seeing in your error message is the return value from TextField.__str__.

You then attach enter_db as an attribute of Register. enter_db is a User instantiated with the values of Register.username, Register.password, and Register.email. Then, still at class creation time, you call Register.enter_db.database and give it the same values as you used to instatiate Register.enter_db.

At no point in time do you assign values to the reg_username, confirm_password, and reg_email fields. This is typically done by providing request.form when you instantiate Register, for example form = Register(request.form). Once you have done this, you would be able to access the values of each field through form.reg_username.data, etc. This part would typically take place in a view function.

The second problem you are having is how you execute your SQL statement.

"INSERT into users (username, pwd, e-mail) VALUES ('%s', '%s', '%s')"
                                                               % (username, password, email)

This uses string interpolation to place the values of username, password, and email directly into the statement before executing it. In addition to this being a bad practice, any ' in one of the values will break your statement. This is what's happening to you because TextField.__str__ includes single quotes around the field's name.

A better (and more secure) approach would be to use a parameterized query. While the specifics vary from driver to driver, I believe the ? is a pretty common implementation. This would change your query to something along the lines of

"INSERT into users (username, pwd, email) VALUES (?, ?, ?)"

You'd then pass the values to cur.execute

cur.execute("INSERT into users (username, pwd, email) VALUES (?, ?, ?)", (username, password, email))

Addressing both of these should put you on the right path.

OTHER TIPS

As documented under Schema Object Names:

Certain objects within MySQL, including database, table, index, column, alias, view, stored procedure, partition, tablespace, and other object names are known as identifiers.

[ deletia ]

Identifiers are converted to Unicode internally. They may contain these characters:

  • Permitted characters in unquoted identifiers:

    • ASCII: [0-9,a-z,A-Z$_] (basic Latin letters, digits 0-9, dollar, underscore)

    • Extended: U+0080 .. U+FFFF

  • Permitted characters in quoted identifiers include the full Unicode Basic Multilingual Plane (BMP), except U+0000:

    • ASCII: U+0001 .. U+007F

    • Extended: U+0080 .. U+FFFF

[ deletia ]

The identifier quote character is the backtick (“`”):

Therefore, to include a hyphen in your e-mail column name (which is generally a bad idea), one must quote the identifier in backticks.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top