This question already has answers here:
How can a name be "unbound" in Python? What code can cause an `UnboundLocalError`?
(3 answers)
How do I correctly clean up a Python object?
(11 answers)
Closed 17 days ago.
So I am a newbie but working on a registration system form in flask/MYSQL
I am receiving this error (UnboundLocalError: local variable 'cursor' referenced before assignment)
After hours of playing with the code and research I need your help.
This is my file, please let me know if theres anything else I need to share.
thank you
from flask import Flask, render_template, json, request
from flask.ext.mysqldb import MySQL
from werkzeug import generate_password_hash, check_password_hash
app = Flask(__name__)
mysql = MySQL()
app.config['MYSQL_DATABASE_USER'] = 'x'
app.config['MYSQL_DATABASE_PASSWORD'] = 'x'
app.config['MYSQL_DATABASE_DB'] = 'x'
app.config['MYSQL_DATABASE_HOST'] = 'x'
mysql.init_app(app)
#app.route('/')
def main():
return render_template('index.html')
#app.route('/login')
def login():
return render_template('login.html')
#app.route('/showSignUp')
def showSignUp():
return render_template('signup.html')
#app.route('/signUp',methods=['POST','GET'])
def signUp():
try:
_name = request.form['inputName']
_email = request.form['inputEmail']
_password = request.form['inputPassword']
# validate the received values
if _name and _email and _password:
# All Good, let's call the MySQL
conn = mysql.connect()
cursor = conn.cursor()
_hashed_password = generate_password_hash(_password)
cursor.callproc('sp_createUser',(_name,_email,_hashed_password))
data = cursor.fetchall()
if len(data) is 0:
conn.commit()
return json.dumps({'message':'User created successfully !'})
else:
return json.dumps({'error':str(data[0])})
else:
return json.dumps({'html':'<span>Enter the required fields</span>'})
except Exception as e:
return json.dumps({'error':str(e)})
finally:
cursor.close()
conn.close()
if __name__ == '__main__':
app.run()
You only define conn and cursor inside the if block checking the form values. If the block is not entered, they're not defined, but you still try to reference them to close them anyway. You should only call close on both if you've defined them. Either move conn = and cursor = to before the if block, or move the close calls to within the block.
However, the bigger problem is that you're misunderstanding/overcomplicating how to use Flask-MySQLdb. It will automatically create the connection and close it when the request is done, which also closes the cursor. Simply use the extension as described in the docs.
...
cur = mysql.connection.cursor()
cur.callproc('sp_createUser', (name, email, hashed_password))
data = cur.fetchall()
...
Personally I would recommend using a context manager to handle opening and closing of your cursor and connection. You can achieve this fairly simply and it is cleaner and easier to debug. This also would eliminate the problem of trying to close a connection or cursor before it is opened in your giant try except block.
from contextlib import closing
# do a bunch of stuff prior to opening connection
with closing(mysql.connect()) as conn:
with closing(conn.cursor()) as cursor:
# do a bunch of stuff and don't worry about running .close()
You can view the docs for closing here.
Using the closing would change your code to be something like this. Although it could use more refactoring, but that is a question for the code review site.
from flask import Flask, render_template, json, request
from flask.ext.mysqldb import MySQL
from werkzeug import generate_password_hash, check_password_hash
from contextlib import closing
app = Flask(__name__)
mysql = MySQL()
app.config['MYSQL_DATABASE_USER'] = 'x'
app.config['MYSQL_DATABASE_PASSWORD'] = 'x'
app.config['MYSQL_DATABASE_DB'] = 'x'
app.config['MYSQL_DATABASE_HOST'] = 'x'
mysql.init_app(app)
#app.route('/')
def main():
return render_template('index.html')
#app.route('/login')
def login():
return render_template('login.html')
#app.route('/showSignUp')
def showSignUp():
return render_template('signup.html')
#app.route('/signUp',methods=['POST','GET'])
def signUp():
try:
_name = request.form['inputName']
_email = request.form['inputEmail']
_password = request.form['inputPassword']
# validate the received values
if _name and _email and _password:
# All Good, let's call the MySQL
with closing(mysql.connect()) as conn:
with closing(conn.cursor()) as cursor:
_hashed_password = generate_password_hash(_password)
cursor.callproc('sp_createUser',(_name,_email,_hashed_password))
data = cursor.fetchall()
if len(data) is 0:
conn.commit()
return json.dumps({'message':'User created successfully !'})
else:
return json.dumps({'error':str(data[0])})
else:
return json.dumps({'html':'<span>Enter the required fields</span>'})
except Exception as e:
return json.dumps({'error':str(e)})
if __name__ == '__main__':
app.run()
Related
I am new to flask and i am writing a basic program for login. Everytime I ammend i end with error mentioned above. below is my code for reference. Can someone please correct me.
#app.route('/')
def index():
return render_template('form_ex.html')
#app.route('/',methods = ['POST'])
def Authenticate():
login = request.form['u']
password = request.form['p']
cursor = mysql.get_db().cursor()
cursor.execute("SELECT * FROM UserLogin WHERE login=%s and password=%s")
data= cursor.fetchone()
if data is None:
return("Username or password incorrect")
else:
return("You are logged in")
By the looks of the code you didn't initialise the MySQL DB, taken from this link the answer is below: Using MySQL in Flask
Firstly you need to install Flask-MySQL package. Using pip for example:
pip install flask-mysql
Next you need to add some configuration and initialize MySQL:
from flask import Flask
from flaskext.mysql import MySQL
app = Flask(__name__)
mysql = MySQL()
app.config['MYSQL_DATABASE_USER'] = 'root'
app.config['MYSQL_DATABASE_PASSWORD'] = 'root'
app.config['MYSQL_DATABASE_DB'] = 'EmpData'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'
mysql.init_app(app)
Now you can get connection and cursor objects and execute raw queries:
conn = mysql.connect()
cursor =conn.cursor()
cursor.execute("SELECT * from User")
data = cursor.fetchone()
I am working on a project to work on a website that connects to a mysql server using flask and sqlAlchemy (Hosted on AWS RDS) and I am following this tutorial but when I try to do (/api/bar) I get this error. When I just do my localhost:8080 it shows "Hello World" perfectly fine.
sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'localhost' ([WinError 10061] No connection could be made because the target machine actively refused it)") (Background on this error at: http://sqlalche.me/e/e3q8)
config.py
database_url = "mysql+pymysql://username:password#localhost:3306/barbeerdrinker"
Here is my __init__.py
from flask import Flask
from flask import jsonify
from flask import make_response
from flask import request
import json
from barbeerdrinker import database
#Flask application
app = Flask(__name__)
#app.route("/")
def hello_world():
return "Hello World"
#app.route("/api/bar", methods=["GET"])
def get_bars():
return jsonify(database.get_bars())
#app.route("/api/bar/<name>", methods=["GETS"])
def find_bar(name):
try:
if name is None:
raise ValueError("Bar is not specified")
bar = database.find_bar(name)
if bar is None:
return make_response("No bar found within given name", 404)
return jsonify(bar)
except ValueError as e:
return make_response(str(e), 400)
except Exception as e:
return make_response(str(e), 500)
#app.route("/api/beers_cheaper_than", methods=["POST"])
def find_beers_cheaper_than():
body = json.loads(request.data)
max_price = body['maxPrice']
return jsonify(database.filter_beers(max_price))
database.py
from sqlalchemy import create_engine
from sqlalchemy import sql
from barbeerdrinker import config
engine = create_engine(config.database_url)
def get_bars():
with engine.connect() as con:
rs = con.execute("SELECT name, address, city, opening, closing, phoneNum FROM bars")
return [dict(row) for row in rs]
def find_bar(name):
with engine.connect() as con:
query = sql.text("SELECT * FROM bars WHERE name = :name;")
rs = con.execute(query, name=name)
result = rs.first()
if result is None:
return None
return dict(result)
def filter_beers(max_price):
with engine.connect() as con:
query = sql.text("SELECT * FROM sells WHERE price < : max_price;")
rs = con.execute(query, max_price=max_price)
results = [dict(row) for row in rs]
for r in results:
r['price'] = float(r['price'])
return results
**Edit: So it seems like the problem is not an issue with my code but a Windows error. One solution I tried to do was to open up the required ports through my firewall to no avail.
I just figured it out, turns out the issue is not a windows issue. The problem is within my config.py:
Instead of:
database_url = "mysql+pymysql://username:password#localhost:3306/barbeerdrinker"
It should be:
database_url = "mysql+pymysql://username:password#**AWSENDPOINT/HOSTNAME**:3306/barbeerdrinker"
I am trying to follow this tutorial:
http://code.tutsplus.com/tutorials/creating-a-web-app-from-scratch-using-python-flask-and-mysql--cms-22972
I have the web app appearing, i can browse between pages and when I click "Sign up" after filling in details I get this error in python:
ERROR:__main__:Exception on /signUp [POST]
OperationalError: (2003, "Can't connect to MySQL server on 'localhost' (10061)")
I'm not sure whats happening here, i have a database called "BucketList.db" in the app.py root folder.
Is there a way to find out where is is getting stuck? or why it cannot connect to the db? I can connect directly to the database using Sqlite and it all seems fine so maybe something not right with how its accessed through localhost?
Any help/guidance would be appreciated! Thanks!!
from flask import Flask, render_template, json, request
from flask_mysqldb import MySQL
from werkzeug import generate_password_hash, check_password_hash
mysql = MySQL()
app = Flask(__name__)
# MySQL configurations
app.config['MYSQL_DATABASE_DB'] = 'BucketList'
app.config['MYSQL_DATABASE_HOST'] = 'localhost'
app.config['MYSQL_DATABASE_PORT'] = '5002'
mysql.init_app(app)
#app.route('/')
def main():
return render_template('index.html')
#app.route('/showSignUp')
def showSignUp():
return render_template('signup.html')
#app.route('/signUp',methods=['POST','GET'])
def signUp():
try:
_name = request.form['inputName']
_email = request.form['inputEmail']
_password = request.form['inputPassword']
# validate the received values
if _name and _email and _password:
# All Good, let's call MySQL
conn = mysql.connect()
cursor = conn.cursor()
_hashed_password = generate_password_hash(_password)
cursor.callproc('sp_createUser',(_name,_email,_hashed_password))
data = cursor.fetchall()
if len(data) is 0:
conn.commit()
return json.dumps({'message':'User created successfully !'})
else:
return json.dumps({'error':str(data[0])})
else:
return json.dumps({'html':'<span>Enter the required fields</span>'})
except Exception as e:
return json.dumps({'error':str(e)})
finally:
cursor.close()
conn.close()
if __name__ == "__main__":
app.run(port=5002)
You may try to avoid connecting again in finally clause. Simply, write conn.close() and cursor.close(). It should resolve your problem.
Here is the code I got to work using the Sqlite implementation suggested by scrineym. It works to the point where you have an app that enters and commits to the database.
Now my only issue is the json parts arent working when I submit/get an error/no field data is written! At least theres one solution that works to the original question!
from flask import Flask, render_template, json, request
from werkzeug import generate_password_hash, check_password_hash
import sqlite3
from flask import g
DATABASE = 'BucketList.db'
#mysql = MySQL()
app = Flask(__name__)
#app.route('/')
def main():
return render_template('index.html')
#app.route('/showSignUp')
def showSignUp():
return render_template('signup.html')
#app.route('/signUp',methods=['POST','GET'])
def signUp():
_name = request.form['inputName']
_email = request.form['inputEmail']
_password = request.form['inputPassword']
# validate the received values
if _name and _email and _password:
print _name, _email
db = g._database = sqlite3.connect(DATABASE)
cursor = get_db().cursor()
print "Database opened"
_hashed_password = generate_password_hash(_password)
print _hashed_password
_userid = str(_name) + str(_hashed_password[0:4])
db.execute('INSERT INTO tbl_user VALUES (?,?,?,?)',(_userid,_name,_email,_hashed_password))
db.commit()
data = cursor.fetchall()
if len(data) is 0:
conn.commit()
return json.dumps({'message':'User created successfully !'})
else:
return json.dumps({'error':str(data[0])})
else:
return json.dumps({'html':'<span>Enter the required fields</span>'})
cursor.close()
db.close()
print "Database closed"
"Print here"
if __name__ == "__main__":
app.run(port=5002)
It's more of a theoratical question but i have been trying to find a correct answer of it for hours and yet i have't arrived at a solution. I have a big flask app and it contains multiple routes.
#app.route('/try'):
#app.route('/new'):
and many others. I am using MySQLdb for database purpose. Before i was having this in the starting of the application.
import MySQLdb as mysql
db = mysql.connect('localhost', 'root', 'password', 'db')
cursor = db.cursor()
It works fine but after a time, it generates a error "Local Variable 'cursor' referenced before assignment.". This may be due to the reason that after a time mysql closes a connection. So, i entered
cursor=db.cursor() in every route function and close it afer i have done the processing like this:
db = mysql.connect('localhost', 'root', 'password', 'db')
#app.route('/')
def home():
cursor=db.cursor()
...some processing...
cursor.close()
return render_template('home.html')
#app.route('/new')
def home_new():
cursor=db.cursor()
...some processing...
cursor.close()
return render_template('homenew.html')
Now i want to ask is this approach right? Should i define a cursor for each request and close it?
This is how I have my MySQLdb setup
def requestConnection():
"Create new connection. Return connection."
convt = cv.conversions.copy()
convt[3] = int
convt
conn = db.connect(host=c.SQL_HOST, port=c.SQL_PORT, user=c.SQL_USER, passwd=c.SQL_PASSWD, db=c.SQL_DB, conv=convt, use_unicode=True, charset="utf8")
return conn
def requestCursor(conn):
return conn.cursor(db.cursors.DictCursor)
Then, at the start of every SQL function I do this:
def executeQuery(query):
"Execute a given query. Used for debug purpouses."
conn = requestConnection()
cur = requestCursor(conn)
cur.execute(query)
r = cur.fetchall()
cur.close()
conn.close()
return r
I change conversions because I had to change int values in DB from Float to int due to my work, but you can skip this step.
If not, you need to import this:
import MySQLdb as db # https://github.com/farcepest/MySQLdb1
import MySQLdb.converters as cv
Hope it helps!
I'm attempting to develop a web app using tornado/torndb and am running into some issues with my database interactions. I've written a "Database" class which wraps torndb in order to provide some common database functionality for my web app. When invoking any of the methods from the Database class I've written there seems to be a problem with the connection to the database:
"ERROR:root:Error connecting to MySQL on localhost"
My constructor opens the connection so I'm a bit confused as to why I see this message after the connection has been opened. I expect this is a scoping and/or GC issue that I am not understanding. The goal is to to create the Database object once and thus just have that
single connection persist throughout the life of the server, the db is stored
The following code snippet does work as expected which led me to the scoping or GC issue possibly:
#!/usr/bin/python
import torndb
class Database:
def __init__(self):
try:
self.__dbh = torndb.Connection(
'localhost',
'mydb',
user = 'myuser',
password = 'mypass')
except Exception as e:
print e
def user_add(self, user, email, passwd):
insert = "INSERT INTO users (username, email, passwd) VALUES " + \
"(%s, %s, %s)" % (user, email, passwd)
rowid = 0
try:
rowid = self.__dbh.execute(insert)
except Exception as e:
print e
if rowid is 0:
return (False, 'User exists');
return (True, None)
if __name__ == "__main__":
print 'Testing'
raw_input('Hit enter to connect to the DB')
d = Database();
users = []
raw_input('Hit enter to create some users')
for i in range(5):
users.append(str(i))
d.user_add(users[i], users[i], users[i])
<- snip ->
The issue is when I try to create a Database object from anywhere other than the main of the module that defines the Database class, for example:
import tornado.ioloop
import tornado.httpserver
import tornado.web
from register import Register
from logon import Logon
from db import Database
class Application(tornado.web.Application):
def __init__(self):
resources = [
(r"/logon", Logon),
(r"/register", Register)
]
self.db = Database()
tornado.web.Application.__init__(self, resources)
try:
self.db.user_add('testuser', 'testemail', 'password')
except Exception as e:
print e
if __name__ == "__main__":
app = Application()
# Start the server.
server = tornado.httpserver.HTTPServer(app)
server.listen(8080)
tornado.ioloop.IOLoop.instance().start()
The above when executed prints (due to the call to self.__dbh.execute()):
ERROR:root:Error connecting to MySQL on localhost
Some other bits of information:
I can connect to the db from the console without any issues.
I'm following this example https://github.com/facebook/tornado/blob/master/demos/blog/blog.py#L60
torndb version is 2.4.1, torndb version is LATEST (pulled using pip).
Questions:
Why is there a difference when I create my Database object in the main of the module that defines the class compared to creating the Database object anywhere else?
The problem was due to the string arguments passed to the query not being escaped, with the following change it works:
def user_add(self, user, email, passwd):
insert = "INSERT INTO users (username, email, passwd) VALUES " + \
"(\'%s\', \'%s\', \'%s\')" % (user, email, passwd)
rowid = 0
try:
rowid = self.__dbh.execute(insert)
except Exception as e:
print e
if rowid is 0:
return (False, 'User exists');
return (True, None)