[英]FLASK SQlite Python - Checking if username is already in database
嘿,有谁能告诉我我的代码中出错了什么? 我想检查用户名是否已存在于数据库中。
整条路线。 它不会给我任何错误,但也不会填补我的数据库。
@app.route('/regist', methods=['GET', 'POST'])
def regist():
if request.method == "POST":
with sql.connect("database.db") as con:
cur = con.cursor()
try:
# flash("register attempted")
username = request.form['username']
password = request.form['password']
passwordencr = request.form['password']
email = request.form['email']
x = cur.execute("SELECT * FROM users WHERE name = ?", (username))
if int(len(x)) > 0:
flash("That username is already taken, please choose another")
return render_template('register.html')
else:
cur.execute("INSERT INTO users (name,password,email) VALUES (?,?,?)",(username,passwordencr,email) )
con.commit()
flash ("Successfully registrated")
except:
con.rollback()
msg = "error in insert operation"
finally:
session['logged_in'] = True
session['username'] = username
gc.collect()
msg = Message('Hello', sender='yourId@gmail.com', recipients=[email])
msg.body = "your username for ak047 is: %s and your password is %s" %(username,password)
mail.send(msg)
return render_template("home.html", msg=msg)
con.close()
gc.collect()
首先,我认为我有一个原始问题的工作代码示例。 但是,我认为您可以使用数据库中的约束更好地解决此重复的用户问题。 看到我的答案的底部。
首先让我们检查当前的代码。 我可以在这里看到几个问题:
try/finally
缩进不正确意味着在try/finally
期间没有活动连接。 缩进
在当前代码中,第6行的try/finally
块需要进一步缩进,以便能够使用第4行的with
语句中建立的连接建立的连接。
正如代码当前所示,连接将在使用时关闭,因此所有数据库访问都将失败。
检查用户
用于检查用户的代码将失败,抛出异常将导致finally被命中并执行rollback
。 无论是否有任何条目,来自execute
的返回值都会在调用len
时抛出异常。
这是我从python shell获得的内容,以显示我的意思:
>>> 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文档为例:
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"
此代码在第1行和第9行连接到database.db
两次。可能这不是最初的意图
制作一个功能,检查用户名和电子邮件是否已在数据库中。
#Models
class User(UserMixin, db.Model):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
username = db.Column(db.String(15), unique=True, nullable=False)
email = db.Column(db.String(50), unique=True, nullable=False)
password = db.Column(db.String(120), unique=True, nullable=False)
created_on = db.Column(db.DateTime, server_default=db.func.now())
updated_on = db.Column(db.DateTime, server_default=db.func.now(), server_onupdate=db.func.now())
tasks = db.relationship('Task', backref='author', lazy='dynamic')
@classmethod
def is_user_name_taken(cls, username):
return db.session.query(db.exists().where(User.username==username)).scalar()
@classmethod
def is_email_taken(cls, email):
return db.session.query(db.exists().where(User.email==email)).scalar()
def __repr__(self):
return '<User %r>' % (self.username)
#User Signup Api
@app.route('/todo/api/v1.0/signup', methods=['POST'])
def signup():
if 'username' not in request.json:
return jsonify({'username': 'must include username'})
if 'email' not in request.json:
return jsonify({'email': 'must include email'})
if 'password' not in request.json:
return jsonify({'password' : 'must include password' })
if User.is_user_name_taken(request.json['username']):
return jsonify({'username': 'This username is already taken!'}), 409
if User.is_email_taken(request.json['email']):
return jsonify({'email': 'This email is already taken!'}), 409
if request.json :
hashed_password = generate_password_hash(request.json['password'], method='sha256')
new_user = User(username=request.json['username'], email=request.json['email'], password=hashed_password)
db.session.add(new_user)
db.session.commit()
return jsonify({'user': 'user created successfully'}), 201
return jsonify({'username': 'must include username',
'password': 'must include password',
'email' : 'must include email' })
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.