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