Во-первых, я думаю, что у меня есть образец рабочего кода для исходной задачи. Тем не менее, я думаю, что вы можете решить эту проблему с дублирующимся пользователем лучше, используя ограничения в базе данных. См. Нижнюю часть моего ответа.
Сначала давайте проверим текущий код. Есть несколько вопросов, которые я могу увидеть здесь:
- Неправильная отступы
try/finally
означает, что нет никакой связи активны в течение try/finally
.
- То, как вы проверяете, есть ли запись с именем пользователя, неверна.
Отступ
В текущем коде try/finally
блока на линии 6 потребностей с отступом один дополнительно для того, чтобы иметь возможность использовать соединение, установленное соединение, сделанное в with
заявления по линии 4.
Поскольку код в настоящее время стоит, соединение будет закрыто к моменту его использования, поэтому доступ к базе данных завершится с ошибкой.
Проверка пользователя
код, используемый для проверки пользователь не сможет, выбрасывая исключение, которое приведет к тому, чтобы окончательно поразить и rollback
быть выполнены. Возвращаемое значение от execute
выдает исключение, когда вы вызываете len
, есть ли какие-либо записи.
Вот что я получаю от питона оболочки, чтобы показать, что я имею в виду:
>>> int(len(cur.execute("select * from people where name_last=:who", {"who": "mike"})))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: object of type 'sqlite3.Cursor' has no len()
Вместо того, чтобы проверить, возвращает ли select
заявление значение, используйте fetchone
и посмотреть, если он возвращает None
:
# No users named `fred`:
>>> cur.execute("select * from people where name_last=:who", {"who": "fred"})
<sqlite3.Cursor object at 0x10bbd0180>
>>> cur.fetchone() is None
True
# At least one user named `mike`:
>>> cur.execute("select * from people where name_last=:who", {"who": "mike"})
<sqlite3.Cursor object at 0x10bbd0180>
>>> cur.fetchone() is None
False
поэтому я думаю, что-то подобное может работать:
def regist():
if request.method == "POST":
with sql.connect("database.db") as con:
cur = con.cursor()
try:
# ... Collecting form info ...
cur.execute("SELECT * FROM users WHERE name = ?", (username))
if cur.fetchone() is not None:
flash("That username is already taken...")
return render_template('register.html')
else:
cur.execute("INSERT INTO users (name,password,email) VALUES (?,?,?)",(username,passwordencr,email))
con.commit()
flash (...)
except:
con.rollback()
finally:
session['logged_in'] = True
session['username'] = username
# ... mailing code ...
Альтернативный подход
Более надежный подход заключается в том, чтобы позволить базе данных взять на себя ответственность за предотвращение дублирования пользователей.
Составьте столбец name
unique
при создании таблицы. Тогда вставка записи с тем же именем пользователя вызовет исключение.Принимая пример из sqlite3 docs:
import sqlite3
con = sqlite3.connect(":memory:")
con.execute("create table person (id integer primary key, firstname varchar unique)")
# Successful, con.commit() is called automatically afterwards
with con:
con.execute("insert into person(firstname) values (?)", ("Joe",))
# con.rollback() is called after the with block finishes with an exception, the
# exception is still raised and must be caught
try:
with con:
con.execute("insert into person(firstname) values (?)", ("Joe",))
except sqlite3.IntegrityError:
print "couldn't add Joe twice"
Я думаю, что ваш код, безусловно, ошибки, вы никогда не должны использовать одеяло, кроме как у вас, если вы не видели бы вы свою ошибку –
Вам не нужно называть 'Int (Len (х)) '. 'len' возвращает целое число. Вам также не нужно сравнивать длину чего-то с 0. 'if len (x)> 0' совпадает с' if x'. – dirn