UPDATE:
I deleted the "drop table if exists" lines, and got the error
python minitwit.py
Traceback (most recent call last):
File "minitwit.py", line 254, in <module>
init_db()
File "minitwit.py", line 57, in init_db
db.cursor().executescript(f.read())
sqlite3.OperationalError: table user already exists
new schema.sql:
create table user (
user_id integer primary key autoincrement,
username text not null,
email text not null,
pw_hash text not null
);
create table follower (
who_id integer,
whom_id integer
);
create table message (
message_id integer primary key autoincrement,
author_id integer not null,
text text not null,
pub_date integer
);
create table access_token (
user_id integer not null,
access_token_text text not null
);
I am just running this free example of Flask called "minitwit," and hoping to modify it slightly. Every time I restart the program, I can't log in with users I previously registered. I checked the database using the command line in the terminal to see if it was really not there, and the tables were empty! How do I get the data in the database to persist every time I restart my program? Thanks!
https://github.com/codeb2cc/flask-examples/blob/master/minitwit/minitwit.py
Flask's demo program "minitwit":
# -*- coding: utf-8 -*-
"""
MiniTwit
~~~~~~~~
A microblogging application written with Flask and sqlite3.
:copyright: (c) 2010 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
import time
from sqlite3 import dbapi2 as sqlite3
from hashlib import md5
from datetime import datetime
from flask import Flask, request, session, url_for, redirect, \
render_template, abort, g, flash, _app_ctx_stack
from werkzeug import check_password_hash, generate_password_hash
# configuration
DATABASE = 'minitwit.db'
PER_PAGE = 30
DEBUG = True
SECRET_KEY = 'development key'
# create our little application :)
app = Flask(__name__)
app.config.from_object(__name__)
app.config.from_envvar('MINITWIT_SETTINGS', silent=True)
def get_db():
"""Opens a new database connection if there is none yet for the
current application context.
"""
top = _app_ctx_stack.top
if not hasattr(top, 'sqlite_db'):
top.sqlite_db = sqlite3.connect(app.config['DATABASE'])
top.sqlite_db.row_factory = sqlite3.Row
return top.sqlite_db
#app.teardown_appcontext
def close_database(exception):
"""Closes the database again at the end of the request."""
top = _app_ctx_stack.top
if hasattr(top, 'sqlite_db'):
top.sqlite_db.close()
def init_db():
"""Creates the database tables."""
with app.app_context():
db = get_db()
with app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
def query_db(query, args=(), one=False):
"""Queries the database and returns a list of dictionaries."""
cur = get_db().execute(query, args)
rv = cur.fetchall()
return (rv[0] if rv else None) if one else rv
def get_user_id(username):
"""Convenience method to look up the id for a username."""
rv = query_db('select user_id from user where username = ?',
[username], one=True)
return rv[0] if rv else None
def format_datetime(timestamp):
"""Format a timestamp for display."""
return datetime.utcfromtimestamp(timestamp).strftime('%Y-%m-%d # %H:%M')
def gravatar_url(email, size=80):
"""Return the gravatar image for the given email address."""
return 'http://www.gravatar.com/avatar/%s?d=identicon&s=%d' % \
(md5(email.strip().lower().encode('utf-8')).hexdigest(), size)
#app.before_request
def before_request():
g.user = None
if 'user_id' in session:
g.user = query_db('select * from user where user_id = ?',
[session['user_id']], one=True)
#app.route('/')
def timeline():
"""Shows a users timeline or if no user is logged in it will
redirect to the public timeline. This timeline shows the user's
messages as well as all the messages of followed users.
"""
if not g.user:
return redirect(url_for('public_timeline'))
return render_template('timeline.html', messages=query_db('''
select message.*, user.* from message, user
where message.author_id = user.user_id and (
user.user_id = ? or
user.user_id in (select whom_id from follower
where who_id = ?))
order by message.pub_date desc limit ?''',
[session['user_id'], session['user_id'], PER_PAGE]))
#app.route('/public')
def public_timeline():
"""Displays the latest messages of all users."""
return render_template('timeline.html', messages=query_db('''
select message.*, user.* from message, user
where message.author_id = user.user_id
order by message.pub_date desc limit ?''', [PER_PAGE]))
#app.route('/<username>')
def user_timeline(username):
"""Display's a users tweets."""
profile_user = query_db('select * from user where username = ?',
[username], one=True)
if profile_user is None:
abort(404)
followed = False
if g.user:
followed = query_db('''select 1 from follower where
follower.who_id = ? and follower.whom_id = ?''',
[session['user_id'], profile_user['user_id']],
one=True) is not None
return render_template('timeline.html', messages=query_db('''
select message.*, user.* from message, user where
user.user_id = message.author_id and user.user_id = ?
order by message.pub_date desc limit ?''',
[profile_user['user_id'], PER_PAGE]), followed=followed,
profile_user=profile_user)
#app.route('/<username>/follow')
def follow_user(username):
"""Adds the current user as follower of the given user."""
if not g.user:
abort(401)
whom_id = get_user_id(username)
if whom_id is None:
abort(404)
db = get_db()
db.execute('insert into follower (who_id, whom_id) values (?, ?)',
[session['user_id'], whom_id])
db.commit()
flash('You are now following "%s"' % username)
return redirect(url_for('user_timeline', username=username))
#app.route('/<username>/unfollow')
def unfollow_user(username):
"""Removes the current user as follower of the given user."""
if not g.user:
abort(401)
whom_id = get_user_id(username)
if whom_id is None:
abort(404)
db = get_db()
db.execute('delete from follower where who_id=? and whom_id=?',
[session['user_id'], whom_id])
db.commit()
flash('You are no longer following "%s"' % username)
return redirect(url_for('user_timeline', username=username))
#app.route('/add_message', methods=['POST'])
def add_message():
"""Registers a new message for the user."""
if 'user_id' not in session:
abort(401)
if request.form['text']:
db = get_db()
db.execute('''insert into message (author_id, text, pub_date)
values (?, ?, ?)''', (session['user_id'], request.form['text'],
int(time.time())))
db.commit()
flash('Your message was recorded')
return redirect(url_for('timeline'))
#app.route('/login', methods=['GET', 'POST'])
def login():
"""Logs the user in."""
if g.user:
return redirect(url_for('timeline'))
error = None
if request.method == 'POST':
user = query_db('''select * from user where
username = ?''', [request.form['username']], one=True)
if user is None:
error = 'Invalid username'
elif not check_password_hash(user['pw_hash'],
request.form['password']):
error = 'Invalid password'
else:
flash('You were logged in')
session['user_id'] = user['user_id']
return redirect(url_for('timeline'))
return render_template('login.html', error=error)
#app.route('/register', methods=['GET', 'POST'])
def register():
"""Registers the user."""
if g.user:
return redirect(url_for('timeline'))
error = None
if request.method == 'POST':
if not request.form['username']:
error = 'You have to enter a username'
elif not request.form['email'] or \
'#' not in request.form['email']:
error = 'You have to enter a valid email address'
elif not request.form['password']:
error = 'You have to enter a password'
elif request.form['password'] != request.form['password2']:
error = 'The two passwords do not match'
elif get_user_id(request.form['username']) is not None:
error = 'The username is already taken'
else:
db = get_db()
db.execute('''insert into user (
username, email, pw_hash) values (?, ?, ?)''',
[request.form['username'], request.form['email'],
generate_password_hash(request.form['password'])])
db.commit()
flash('You were successfully registered and can login now')
return redirect(url_for('login'))
return render_template('register.html', error=error)
#app.route('/logout')
def logout():
"""Logs the user out."""
flash('You were logged out')
session.pop('user_id', None)
return redirect(url_for('public_timeline'))
# add some filters to jinja
app.jinja_env.filters['datetimeformat'] = format_datetime
app.jinja_env.filters['gravatar'] = gravatar_url
if __name__ == '__main__':
init_db()
app.run('127.0.0.1', debug=True, port=5000, ssl_context=('xxx', 'xxx'))
schema.sql: (This also came with the demo, but I added the access_token table because I was trying to do OAuth2)
drop table if exists user;
create table user (
user_id integer primary key autoincrement,
username text not null,
email text not null,
pw_hash text not null
);
drop table if exists follower;
create table follower (
who_id integer,
whom_id integer
);
drop table if exists message;
create table message (
message_id integer primary key autoincrement,
author_id integer not null,
text text not null,
pub_date integer
);
drop table if exists access_token;
create table access_token (
user_id integer not null,
access_token_text text not null
);
I just added the try-except block to this init_db() method, and also deleted the "drop table if exists" lines from schema.sql (see "update" in my question), and now I can restart the program and load the saved data from the database.
def init_db():
"""Creates the database tables."""
with app.app_context():
db = get_db()
with app.open_resource('schema.sql', mode='r') as f:
try:
db.cursor().executescript(f.read())
except sqlite3.OperationalError, msg:
print msg
db.commit()
Related
I'm trying to run a function to add a user to a flask website built with python
here is the function
def add_user(self, name, email, password, is_admin):
query = f"""
SELECT name FROM loginUsers WHERE email='{email}';
"""
response = self.conn.execute(query)
existing_user = [rec for rec in response]
if not existing_user:
created_on = datetime.utcnow()
user = User(name=name, email=email, created_on=created_on, is_admin=is_admin).set_password(password)
print(user)
query = f"""
INSERT INTO loginUsers
(name, email, created_on, password, is_admin)
VALUES
('{name}', '{email}', '{created_on}', '{pass_hashed}', {is_admin});
"""
cursor = self.conn.cursor()
cursor.execute(query)
self.conn.commit()
print('New user created')
cursor.close()
return f'User {name} - {password} is already exist'
I've tried putting in my own values multiple times and its not adding to the loginUsers table. PLEASE HELP!!!! Can this be demonstrated with example?
def add_user(self, name, email, password, is_admin):
query = f"""
SELECT name FROM loginUsers WHERE email='{email}';
"""
response = self.conn.execute(query)
existing_user = [rec for rec in response]
if not existing_user:
created_on = datetime.utcnow()
user = User(name=name, email=email, created_on=created_on, is_admin=is_admin).set_password(password)
print(user)
query = f"""
INSERT INTO loginUsers
(name, email, created_on, password, is_admin)
VALUES
('{name}', '{email}', '{created_on}', '{pass_hashed}', {is_admin});
"""
cursor = self.conn.cursor()
cursor.execute(query)
self.conn.commit()
print('New user created')
cursor.close()
return f'User {name} - {password} is already exist'
enter image description here
I am making a authentication web app , and trying to insert data in database and commiting it too but still doesn't work . I am using flask-sqlite,It says success but when I go my /list endpoint it is blank and even does't print's anything in console . Here's the full code
from flask import Flask, render_template, request, url_for
import sqlite3
app = Flask(__name__)
con = sqlite3.connect("details.db")
print("Database opened successfully")
con.execute("create table if not exists Users (id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT UNIQUE NOT NULL, password TEXT NOT NULL)")
print("Table created successfully")
con.close()
#app.route('/signup', methods=['GET', 'POST'])
def signup():
msg = ""
if request.method == "POST":
try:
email = request.form["email"]
password = request.form["password"]
print(name, email)
with sqlite3.connect("details.db") as con:
cur = con.cursor()
cur.execute("INSERT into Users (email, password) values (%s, %s)",(email, password))
cur.commit()
msg = "User successfully Added"
except Exception as err:
con.rollback()
msg = "Sorry We Can't Signup You"
finally:
return render_template("res.html",msg = msg)
con.close()
#app.route("/signup-page")
def signupTemplate():
return render_template('index.html')
#app.route("/list")
def list_users():
con = sqlite3.connect("details.db")
con.row_factory = sqlite3.Row
cur = con.cursor()
cur.execute("select * from Users")
row = cur.fetchall()
email = ""
password = ""
for rows in row:
email = rows["email"]
password = rows["password"]
con.close()
return render_template("list.html", email=email,password=password)
app.run(debug=True)
change this two lines.
cur.execute(f"INSERT into Users (email, password) values ('{email}', '{password}')")
con.commit()
you can use format string in your query and connection.commit() not cursor.
What I am trying to do is to get the email id and compare against the SQLite table.
If email exists in the table then I update the table with the emailid and random generated password and mail them.
If email does not exists in the table then I use insert query to enter the email as well as random generated password into the table.
After the insert or the update query is fired I mail them the generated password using Flask-mail
However I am unable to execute it
def sqliteconfig():
try:
conn = sqlite3.connect('auth.db',check_same_thread=False)
cur = conn.cursor()
conn.execute('CREATE TABLE IF NOT EXISTS auth (AID INTEGER PRIMARY KEY AUTOINCREMENT, emailid TEXT UNIQUE, otp TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP)')
cur.close()
except Exception as e:
print(e)
return 'DatabaseDown'
# return 'DatabaseDown'
return conn
#bp.route('/')
def index_redirect():
return redirect(url_for('devcon.login'))
#bp.route('/login',methods=['GET','POST'])
def login():
conn = sqliteconfig()
cur = conn.cursor()
if request.method == 'POST':
emailid = request.form['emailid']
if emailid != "":
s = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"
passlen = 8
password = "".join(random.sample(s,passlen ))
conn.execute('select count(*) from auth where emailid=(?)',[emailid])
rows = cur.fetchall();
if len(rows) == 0:
conn.execute('insert into auth(email,otp) values(?,?)',[emailid,password])
conn.commit()
elif len(rows)==1:
conn.execute('update auth SET otp=(?) where emailid=(?)',[emailid,password])
conn.commit()
return str(rows)
return render_template("login/login.html")
The Particular problem I am facing right know is SELECT COUNT query returns nothing and INSERT query throws constraint violation error of unique emailid.
I am looking forward if there is any better way to do this
For the first error where SELECT COUNT returns nothing, in Sqlite3 select * is used instead of select count(*). Therefore your code should be:
rows = conn.execute('SELECT * FROM auth WHERE emailid = ?',(emailid,)).fetchall()
For the second insertion error, you may already have an equivalent emailid value stored into auth. That is the only reason why you would have a constraint violation of an unique emailid.
Another (potential) error is that you set otp to emailid and password to emailid, while the order should be reversed:
conn.execute('update auth SET otp=(?) where emailid=(?)',[emailid,password])
Instead, do this:
conn.execute('UPDATE auth SET otp = ? WHERE emailid = ?',(password, emailid))
Final code:
def sqliteconfig():
try:
conn = sqlite3.connect('auth.db',check_same_thread=False)
cur = conn.cursor()
conn.execute('CREATE TABLE IF NOT EXISTS auth (AID INTEGER PRIMARY KEY AUTOINCREMENT, emailid TEXT UNIQUE, otp TEXT, created_at TEXT DEFAULT CURRENT_TIMESTAMP)')
cur.close()
except Exception as e:
print(e)
return 'DatabaseDown'
# return 'DatabaseDown'
return conn
#bp.route('/')
def index_redirect():
return redirect(url_for('devcon.login'))
#bp.route('/login',methods=['GET','POST'])
def login():
conn = sqliteconfig()
cur = conn.cursor()
if request.method == 'POST':
emailid = request.form['emailid']
if emailid != "":
s = "abcdefghijklmnopqrstuvwxyz01234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ"
passlen = 8
password = "".join(random.sample(s,passlen ))
rows = conn.execute('SELECT * FROM auth WHERE emailid = ?',(emailid,)).fetchall()
if len(rows) == 0:
conn.execute('INSERT into auth (email, otp) VALUES (?, ?)',(emailid, password))
conn.commit()
elif len(rows)==1:
conn.execute('UPDATE auth SET otp = ? WHERE emailid = ?',(emailid, password))
conn.commit()
return str(rows)
return render_template("login/login.html")
I am learning python flask and developing a web page where I can register and store user details in encrypted format in MySQL database using XAMPP server and decrypting the same to verify user details during login.
Here, while storing the encrypted password in database, the AES_ENCRYPT function is encrypting the string 'password' itself and not the one that is entered in the form. And the AES_DECRYPT function does not retrieve back the string during login verification, so, it always shows invalid password. How to resolve this?
from flask import Flask, request, render_template
app = Flask(__name__)
import mysql.connector as MySQLdb
#app.route('/')
#app.route('/login')
def login():
return render_template('login.html')
#app.route('/register')
def register():
return render_template('register.html')
def valid_login(uname, password):
# Open database connection
db = MySQLdb.connect(
host="localhost",
user="root",
passwd="",
database="sam"
)
cursor = db.cursor()
sql = "SELECT AES_DECRYPT(AES_ENCRYPT('passcode', 'usa2010'), 'usa2010') FROM user WHERE username = %s"
value =(uname, )
cursor.execute(sql, value)
row = cursor.fetchone()
print(row[0])
if password == row[0].decode():
return 1
else:
return 0
# disconnect from server
db.close()
def valid_insert(uname, email, password, phone, city):
# Open database connection
db = MySQLdb.connect(
host="localhost",
user="root",
passwd="",
database="sam"
)
cursor = db.cursor()
sql = "INSERT INTO user VALUES (%s, %s, AES_ENCRYPT(password, 'usa2010'), %s, %s)"
val = (uname, email, phone, city)
cursor.execute(sql, val)
db.commit()
if cursor.rowcount > 0:
return 1
else:
return 0
# disconnect from server
db.close()
#app.route('/check', methods=['POST'])
def check():
error = None
if request.method == 'POST':
if valid_login(request.form['uname'], request.form['pass']):
return render_template('home.html')
else:
print('Invalid username/password')
return render_template('login.html')
#app.route('/login_insert', methods=['POST'])
def insert():
error = None
if request.method == 'POST':
if valid_insert(request.form['uname'], request.form['email'], request.form['pass'], request.form['phone'], request.form['city']):
return render_template('login.html')
else:
error = 'Username already taken.'
return render_template('register.html')
if __name__ == '__main__':
app.run()
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.