简体   繁体   English

FLASK SQlite Python - 检查用户名是否已在数据库中

[英]FLASK SQlite Python - Checking if username is already in database

Hey can anyone tell me what I'm doing wrong in my code? 嘿,有谁能告诉我我的代码中出错了什么? I want to check whether an username is already in the database or not. 我想检查用户名是否已存在于数据库中。

Whole Route. 整条路线。 It wont give me any errors but also wont fill my 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()

First, I think I have a working code sample for the original problem. 首先,我认为我有一个原始问题的工作代码示例。 However, I think you can solve this duplicate user problem better using constraints within the database. 但是,我认为您可以使用数据库中的约束更好地解决此重复的用户问题。 See the bottom of my answer. 看到我的答案的底部。

First let's check the current code. 首先让我们检查当前的代码。 There are a couple of issues I can see here: 我可以在这里看到几个问题:

  1. Incorrect indent for try/finally means there's no connection active during the try/finally . try/finally缩进不正确意味着在try/finally期间没有活动连接。
  2. The way you're checking for whether there's an entry with the username isn't correct. 您检查是否有包含用户名的条目的方式不正确。

Indent 缩进

In the current code, the try/finally block at line 6 needs to be indented one further in order to be able to use the connection established by the connection made in the with statement on line 4. 在当前代码中,第6行的try/finally块需要进一步缩进,以便能够使用第4行的with语句中建立的连接建立的连接。

As the code currently stands, the connection will have been closed by the time it's used, so all database access will fail. 正如代码当前所示,连接将在使用时关闭,因此所有数据库访问都将失败。

Checking for a user 检查用户

The code used to check for a user will fail, throwing an exception which will cause the finally to be hit and the rollback to be executed. 用于检查用户的代码将失败,抛出异常将导致finally被命中并执行rollback The return value from execute throws an exception when you call len , whether or not there are any entries. 无论是否有任何条目,来自execute的返回值都会在调用len时抛出异常。

Here's what I get from a python shell to show what I mean: 这是我从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()

Instead, to check whether a select statement returns a value, use fetchone and see if it returns None : 相反,要检查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

I think therefore something like this might work: 我认为这样的事情可能有用:

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 ...

Alternative approach 替代方法

A more robust approach would be to let the database take responsibility for preventing duplicate users. 更强大的方法是让数据库负责防止重复用户。

Make the name column unique when creating the table. 创建表时,使nameunique Then inserting a record with the same username will throw an exception. 然后插入具有相同用户名的记录将引发异常。 Taking an example from the sqlite3 docs : 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两次。可能这不是最初的意图

Make one function, who check username and email is already in database or not. 制作一个功能,检查用户名和电子邮件是否已在数据库中。

#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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM