Problems using sqlAlchemy to execute SQL queries on my database - python

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"

Related

How to configure DB in a Flask app dynamicly?

I'm working on app, where user have to enter database connection parametrs by hands
So I've made an api here it is:
from flask_mysqldb import MySQL
from flask import Flask, request
import MySQLdb.cursors
app = Flask(__name__)
# /hello
#app.route("/hello", methods=['GET'])
def hello():
return "Hello word"
# /get_tables
#app.route(f"/get_tables", methods=['GET'])
def get_tables():
host = request.args.get('host', type=str)
user = request.args.get('user', type=str)
password = request.args.get('password', type=str)
database = request.args.get('database', type=str)
app.config['MYSQL_HOST'] = "localhost"
app.config['MYSQL_USER'] = "root"
app.config['MYSQL_PASSWORD'] = "password"
app.config['MYSQL_DB'] = "restaurant"
mysql = MySQL(app)
cursor = mysql.connection.cursor(MySQLdb.cursors.DictCursor)
query = "SHOW TABLES"
cursor.execute(query)
records = cursor.fetchone()
print(records)
return records
"hello" endpoint is working fine, but when run "get_tables" I recieve an error:
AssertionError: The setup method 'teardown_appcontext' can no longer be called on the application. It has already handled its first request, any changes will not be applied consistently. Make sure all imports, decorators, functions, etc. needed to set up the application are done before running it.
I also was trying to debug my api and found out that errorr ocures on a mysql = MySQL(app) line
What can I do to solve this problem? or maybe it's better not to use api at all and just connect to DB from ui?

python connection to DB throwing error

I am new to using python to connect to a mysql DB and I am getting the following error:
OperationalError: (pymysql.err.OperationalError) (1045, u"Access denied for user 'xxxxxxadmin'#'xx.xx.xx.xx' (using password: YES)") (Background on this error at: http://sqlalche.me/e/e3q8)
xx.xxx.216.44 - - [02/Apr/2018 17:27:49] "GET /testconnect HTTP/1.1" 500 -
This is most of the connect script in my python file:
#!/usr/bin/python3
from flask import Flask, request
from flask_restful import Resource, Api
from sqlalchemy import create_engine
from json import dumps
from flask.ext.jsonpify import jsonify
db_connect = create_engine("mysql+pymysql://xxxxxxxadmin:password#,mymaindb.xxxxxxxx.us-east-2.rds.amazonaws.com:3306/myDBname")
app = Flask(__name__)
api = Api(app)
class TestConnect(Resource):
def get(self):
conn = db_connect.connect() # connect to database
query = conn.execute("select * from Players") # This line performs query and returns json result
return {'employees': [i[0] for i in query.cursor.fetchall()]} # Fetches first column that is Employee ID
api.add_resource(TestConnect, '/testconnect') # Route_1
if __name__ == '__main__':
app.run(host='0.0.0.0', debug = False)
Other background:
But when I try to connect to the same mysql database using the exact same credentials via the command line on the server running the python script I am able to get in.
Not sure how to test more to get a better error result that will help me figure this issue out.
UPDATE
So I was able to connect to my DB via mysql workbench with the connection strings and information I have in the python script. Does this mean my python script is doing something wrong?
Why not use:
mysql+pymysql://xxxxxxxadmin:password#mymaindb.xxxxxxxx.us-east-2.rds.amazonaws.com:3306/myDBname
instead of
mysql+pymysql://xxxxxxxadmin:password#**,**mymaindb.xxxxxxxx.us-east-2.rds.amazonaws.com:3306/myDBname
Not sure why you're connection string has a comma. Might just be a typo?
On that note, I usually build the connection URL before passing it to create_engine just to make it easier to manage in the future incase I have to pull the actual values from the environmental variables:
HOST = "mymaindb.xxxxxxxx.us-east-2.rds.amazonaws.com"
PORT = 3306
USERNAME = "xxxxxxxadmin"
PASSWORD = "password"
DBNAME = "myDBname"
CONNECTION_URL = 'mysql+pymysql://%s:%s#%s:%s/%s' % (
USERNAME,
PASSWORD,
HOST,
PORT,
DBNAME
)

`TypeError: argument 2 must be a connection, cursor or None` in Psycopg2

I have a heroku pipeline set up, and have just enabled review apps for it. It is using the same codebase as my staging and production apps, same settings files and everything.
When the review app spins up, it can connect to the created DB and run migrations. When I try to connect to the app in the browser, I get
`TypeError: argument 2 must be a connection, cursor or None` in `psycopg2/_json.py, register_json:139`
Top of stack is:
`django.contrib.sites.models._get_site_by_id`.
I've attached the Opbeat output of the error frame at the bottom of this post.
Settings file is linked.
When I set DEBUG=True, everything works fine. Which might suggest an ALLOWED_HOSTS issue, but when I set ALLOWED_HOSTS to '*' with DEBUG=False, it still errors?
What is wrong with my setup? This works in staging, and production, but not the review apps.
tldr
# example borked
engine = sqlalchemy.create_engine('postgresql+psycopg2://', creator=lambda: 'asdf')
# example works
engine = sqlalchemy.create_engine('postgresql+psycopg2://', creator=lambda: conn)
I think this might be an error from one of the following:
psycopg2.extensions.register_type
_connect
cpython
static PyObject *psyco_register_type
static PyObject * psyco_connect
examples
https://github.com/psycopg/psycopg2/search?q=register_type&unscoped_q=register_type
Specifcally the error can be raised from :
psycopg2.
_ipaddress.py
_json.py
_psycopg.cpython-37m-darwin.so
_range.py
extensions.py
extras.py
in my case:
_ext.register_type(_ext.UUID, conn_or_curs)
Apparently this is what it does:
https://github.com/psycopg/psycopg2/blob/master/doc/src/extensions.rst#database-types-casting-functions
the code in my case which caused the issue was the create_engine keyword creator=get_connection in the following example:
from psycopg2.pool import ThreadedConnectionPool
from contextlib import contextmanager
import sqlalchemy
conn_string = "host='127.0.0.1' dbname='postgres' user='someuser' password='somepassword'"
top = ThreadedConnectionPool(1, 250, conn_string)
#contextmanager
def get_connection():
try:
connection = top.getconn()
yield connection
finally:
top.putconn(connection)
#contextmanager
def get_cursor(commit=False):
with get_connection() as connection:
cursor = connection.cursor(
cursor_factory=psycopg2.extras.RealDictCursor)
try:
yield cursor
if commit:
connection.commit()
finally:
cursor.close()
engine = sqlalchemy.create_engine('postgresql+psycopg2://', creator=get_connection)
#contextmanager
def get_sqlalchemy_engine():
yield engine.connect()
what caused the issue:
with get_sqlalchemy_engine() as engine:
pd.DataFrame([1]).to_sql('asdf', engine, if_exists='replace')
And what fixed the issue:
#contextmanager
def get_sqlalchemy_engine():
with get_connection() as conn:
try:
engine = sqlalchemy.create_engine('postgresql+psycopg2://', creator=lambda: conn)
# engine = sqlalchemy.create_engine('postgresql+psycopg2://', creator=lambda: 'asdf')
yield engine
finally:
engine.dispose()
further research indicates the following:
JSON = new_type((oid, ), name, typecast_json)
if array_oid is not None:
JSONARRAY = new_array_type((array_oid, ), "%sARRAY" % name, JSON)
else:
JSONARRAY = None
return JSON, JSONARRAY
basically conn_or_curs is not a connection or cursor, but rather some other thing,
register_type(JSON, not globally and conn_or_curs or None)
register_type(JSONARRAY, not globally and conn_or_curs or None)
https://github.com/psycopg/psycopg2/blob/f947c0e6be1d2c3ea8d2d8badf683b95bd213444/psycopg/psycopgmodule.c#L189
https://github.com/psycopg/psycopg2/blob/f947c0e6be1d2c3ea8d2d8badf683b95bd213444/psycopg/psycopgmodule.c#L260

MySQL connection times out after a while (Python, MySQL, FLASK)

I'm currently running an flask python application running on an NGINX server with the help of uWGI. The static pages are always reachable but the pages that use a connection (MySQL) time out after 2 minutes. What's going on? They become simply become unavailable.
Things I have tried:
Not using a global
working with pools
turning off firewall
.
# using python version 2.7.10
from flask import Flask, jsonify, request, session
import mysql.connector.pooling
#Make a connection with the DB
dbconfig = {
"host" : "12.34.5.78",
"database": "db",
"user": "user",
"password": "pass"
}
conn = mysql.connector.connect(pool_name = "mypool",
pool_size = 6,
**dbconfig)
#Define the root
app = Flask(__name__)
#Landings page
#app.route('/')
def index():
return "Hello World."
# return all resources by name
#app.route('/resources', methods=['GET'])
def allResourceNames():
conn1 = mysql.connector.connect(pool_name="mypool")
reader = conn1.cursor()
query = ("SELECT name FROM resources")
reader.execute(query)
resources = []
for name in reader:
resources.append({'name' : name[0]})
reader.close()
conn1.close()
return jsonify({"resources" : resources})
if __name__ == "__main__":
app.run(debug=True)
According to MySQL Python Connector Doc
you may want to set connection_timeout as connect option. E.g.,
conn = mysql.connector.connect(pool_name = "mypool",
pool_size = 6, connection_timeout=3600,
**dbconfig)

Simple Flask app - can't connect to database on localhost?

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)

Categories

Resources