Python Flask SQL Register Login Page "hash must be unicode or bytes, not long"

Question:

Im trying to create a login / register page. My register page works and I see the information and hashed passwords added. When I try to login, I get “hash must be unicode or bytes, not long” flashed. Please help!

    @app.route('/login/', methods=['GET','POST'])
    def login():
        try:
            c,conn = connection()

            if request.method == 'POST':

                data = c.execute("SELECT * FROM users WHERE username = %s",
                        thwart(request.form['username']))

                if sha256_crypt.verify(request.form['password'], data):
                    session['logged_in'] = True
                    session['username'] = request.form['username']
                    flash('You are now logged in.'+str(session['username']))
                    return redirect(url_for('dashboard'))

            else:
                error = 'Invalid credentials. Try again'

            return render_template('login.html', error=error)
        except Exception, e:
                flash(e)
------------------------------------------------------------------

     import MySQLdb

     def connection():
         conn = MySQLdb.connect(host="localhost",
                                user = "root",
                                passwd = "julie774",
                                db = "PYTHONTUT")
         c = conn.cursor()

         return c, conn
Asked By: Anekdotin

||

Answers:

data = c.execute(“SELECT * FROM users WHERE username = %s”,
thwart(request.form[‘username’]))

cursor.execute just executes the query and returns the number of affected rows. (see pydoc of cursor.execute). Thus in your data variable you have the number of found rows.

Instead you have to fetch the data from the cursor. Also since you are requesting all the columns from user (*), you will have to extract only a particular column (the index of it — see the end note).

c.execute("SELECT password FROM users WHERE username = %s",
                    thwart(request.form['username']))
data = c.fetchone()
# c.fetchone() returns None if no row has been found

if sha256_crypt.verify(request.form['password'], data[0]):
    ...

In your example you are connecting to database without specifying the type of the cursor, thus c.fetchone() will return a tuple (for example (1L, 'John Doe', '392347')). And to select particular column you have to use numerical index — data[1] to retrieve 'John Doe'.

If you want named dictionary instead, you will have to specify it when connecting to db.

conn = MySQLdb.connect(host="localhost",
                       user = "root",
                       passwd = "***",
                       db = "PYTHONTUT",
                       cursorclass=MySQLdb.cursors.DictCursor
                       )

Then c.fetchone() will return a dict instead (e.g. {'id': 1L, 'name': 'John Doe', 'password': '392347'}) so you can use more readable data['name'] etc.

Answered By: Peter Uhnak
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.