Не удается отправить данные WTForms в MySQL

Невозможно отправить данные WTForms в базу данных MySQL, поскольку отправленные данные все еще находятся в несвязанных полях и т. д., хотя я пытался преобразовать их в строку. Не знаю, что делать.

Я пытаюсь создать регистрационную форму, используя Flask и WTForms. Я получаю следующую ошибку, когда перехожу к вводу данных (имя пользователя, пароль, адрес электронной почты) в базу данных MySQL:

Я пробовал искать везде, но нигде не объясняется, как я мог бы это исправить. Ниже приведен соответствующий код:

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)

Я новичок в веб-разработке с использованием Flask/WTForms.


person Jason Decastro    schedule 19.02.2014    source источник
comment
Я ничего не знаю о WTForms, но это не может быть правдой: вы делаете всю работу с базой данных в самом определении формы на уровне класса. Предположительно, вам нужно сделать это в обработчике, который обрабатывает форму, где он будет принимать данные POST и проверять их.   -  person Daniel Roseman    schedule 19.02.2014


Ответы (2)


Есть две проблемы с вашим кодом.

Первая проблема связана с тем, как вы определяете свой класс.

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)

Ваши вызовы str происходят при создании класса и преобразовании атрибутов reg_username, confirm_password и reg_email в строки. Значение, которое вы видите в своем сообщении об ошибке, является возвращаемым значением из TextField.__str__.

Затем вы прикрепляете enter_db в качестве атрибута Register. enter_db — это User, созданный со значениями Register.username, Register.password и Register.email. Затем, еще во время создания класса, вы вызываете Register.enter_db.database и даете ему те же значения, которые вы использовали для создания Register.enter_db.

Вы никогда не присваиваете значения полям reg_username, confirm_password и reg_email. Обычно это делается путем указания request.form при создании экземпляра Register, например form = Register(request.form). Как только вы это сделаете, вы сможете получить доступ к значениям каждого поля через form.reg_username.data и т. д. Эта часть обычно выполняется в функции представления.

Вторая проблема, с которой вы сталкиваетесь, заключается в том, как вы выполняете оператор SQL.

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

При этом используется интерполяция строк, чтобы поместить значения username, password и email непосредственно в оператор перед его выполнением. В дополнение к тому, что это плохая практика, любое ' в одном из значений нарушит ваше утверждение. Это то, что происходит с вами, потому что TextField.__str__ включает одинарные кавычки вокруг имени поля.

Лучшим (и более безопасным) подходом было бы использование параметризованного запроса. Хотя особенности варьируются от драйвера к драйверу, я считаю, что ? является довольно распространенной реализацией. Это изменит ваш запрос на что-то вроде строк

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

Затем вы должны передать значения cur.execute

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

Решение обоих этих вопросов должно поставить вас на правильный путь.

person dirn    schedule 19.02.2014

Как описано в разделе Имена объектов схемы:

Некоторые объекты в MySQL, включая базу данных, таблицу, индекс, столбец, псевдоним, представление, хранимую процедуру, раздел, табличное пространство и другие имена объектов, известны как идентификаторы.

[ deletia ]

Идентификаторы преобразуются в Unicode внутри. Они могут содержать следующие символы:

  • Допустимые символы в идентификаторах без кавычек:

    • ASCII: [0-9,a-z,A-Z$_] (основные латинские буквы, цифры 0-9, доллар, подчеркивание)

    • Расширенный: U+0080 .. U+FFFF

  • Допустимые символы в идентификаторах в кавычках включают полную базовую многоязычную плоскость Unicode (BMP), кроме U+0000:

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

    • Расширенный: U+0080 .. U+FFFF

[ deletia ]

Символ кавычки идентификатора — это обратная кавычка («`»):

Поэтому, чтобы включить дефис в имя столбца e-mail (что, как правило, является плохой идеей), необходимо заключить идентификатор в обратных кавычках.

person eggyal    schedule 19.02.2014
comment
Удаление тире из электронной почты дало определенные результаты, за что я должен поблагодарить вас, но теперь я получаю эту ошибку: i.imgur.com/1PvXtUV.png -- Я не могу найти ничего неправильного в синтаксисе "имя пользователя"? - person Jason Decastro; 19.02.2014