unable to connect to mysql server using flask and pyodbc - python

I use the below code for connecting to MYSQL DATABASE using flask and pyodbc package. AS I try to run a flask project.
app.py
from dotenv import load_dotenv
from flask_migrate import Migrate
from flask_cors import CORS
from api import create_app, init_db
from api.common.models.models import db
import os
load_dotenv()
app_name = os.environ.get('FLASK_APP') or ''
app = create_app()
# security
cors_allowed_origins = os.environ.get('CORS_ALLOWED_ORIGINS', [])
CORS(app) # , origins=cors_allowed_origins
# sqlalchemy
app.config['SQLALCHEMY_DATABASE_URI'] = "mssql+pyodbc://USERNAME:PASSWORD#./DBNAME?driver=ODBC+Driver+17+for+SQL+Server"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = FALSE
db = init_db(app)
migrate = Migrate(app, db)
#app.route('/')
def home():
str = 'Hello World {0}'.format(app_name)
return str
if __name__=='__main__':
app.run()
I get the following error:
sqlalchemy.exc.OperationalError: (pyodbc.OperationalError) ('HYT00', '[HYT00] [Microsoft][ODBC Driver 17 for SQL Server]Login timeout expired (0) (SQLDriverConnect)')

Your issue is with the connection string, you are trying to connect to MySql but the connection string is to connect to MSSQL:
"mssql+pyodbc://USERNAME:PASSWORD#./DBNAME?driver=ODBC+Driver+17+for+SQL+Server"
But for MYSQL is one of the following:
# default
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://scott:tiger#localhost/foo'
# mysqlclient (a maintained fork of MySQL-Python)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+mysqldb://scott:tiger#localhost/foo'
# PyMySQL
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://scott:tiger#localhost/foo'
Check the official documentation:
Database Urls

Related

Flask-MySQL ignore host parameter

I'm trying to write a Flask miniapp to connect with a MySQL database. To connect with the database, I use flask-mysql, calling it as this way
from flask import Flask, render_template, redirect
from flaskext.mysql import MySQL
SECRET_KEY='5f352379324c22463451387a0aec5d2f'
app = Flask(__name__)
app.secret_key = SECRET_KEY
mydb = MySQL(app, prefix="mydb", host='172.17.0.2', user='testusr', password='test', db='testDB')
(...)
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5000)
But, when I run the application, it shows this error
pymysql.err.OperationalError: (1044, "Access denied for user 'testusr'#'%' to database 'testDB'")
If I run it from a Docker container, I get a similar error, replacing "%" with "localhost" (in this case, it's not able to connect, due to the database is out of the container)
pymysql.err.OperationalError: (2003, "Can't connect to MySQL server on 'localhost' ([Errno 99] Cannot assign requested address)")
172.17.0.1 - - [23/Jun/2021 18:00:29] "GET / HTTP/1.1" 500 -
I tried to initialize flask-mysql using other this way, with the same error
app.config['MYSQL_HOST'] = '172.17.0.2'
app.config['MYSQL_USER'] = 'testusr'
app.config['MYSQL_PASSWORD'] = 'test'
app.config['MYSQL_DB'] = 'testDB'
mydb = MySQL(app)
Where can be the error?
Solved changing the connector from flask-mysql to mysql-connector
import mysql.connector
SECRET_KEY='5f352379324c22463451387a0aec5d2f'
app = Flask(__name__)
app.secret_key = SECRET_KEY
mydb = mysql.connector.connect(
host="172.17.0.2",
user="testusr",
password="test",
database="testDB"
)

Flask: db is not being referenced properly when importing into my database seeder script

# project\__init__.py
from flask import Flask
from flask_mysqldb import MySQL
from .config import app_config
db = MySQL()
def create_app(config_name):
app = Flask(__name__,
instance_path=os.path.join(os.path.dirname(__file__), 'instance'),
instance_relative_config=True)
app.config.from_object(app_config[config_name])
db.init_app(app)
print(db) # prints <flask_mysqldb.MySQL object at 0x000002A13710FC10>
# project/main.py
from . import db
#main.route('/foobar')
def foobar():
print(db) # prints <flask_mysqldb.MySQL object at 0x000002A13710FC10>
# project/database/seed_shipment.py
from project import create_app, db
def foo():
.
.
.
def goo()
.
.
.
if __name__ == '__main__':
config_name = os.getenv('FLASK_ENV')
app = create_app(config_name)
cursor = db.connection.cursor()
print(db) # prints <flask_mysqldb.MySQL object at 0x000002056B4EFD60>
print(db.connection) # returns None
for x in range(20):
# code which generates dummy data using foo() and goo()
cursor.execute("INSERT INTO shipment (column1, column2) VALUES (%s)", (var1, var2))
db.connection.commit()
My database connection works fine when I host the app and carry out CRUD operations using the interface in my browser. Such as login, sign up, create a shipment.
Note that I am not executing flask run from my terminal but instead python -m project.run, here is the code of this script:
# project/run.py
import os
from . import create_app
config_name = os.getenv('FLASK_ENV')
app = create_app(config_name)
if __name__ == '__main__':
app.run()
However, when I run python -m project.database.seed_shipment db seems to reference a different MySQL instance which has no connection. See the print results in the comments in my code.
My database connection works fine when I host the app and carry out CRUD operations using the interface in my browser. Such as login, sign up, create a shipment.
This indicates to me that you are correctly connecting to your db for each request.
However, when I run python -m project.database.seed_shipment db seems to reference a different MySQL instance which has no connection. See the print results in the comments in my code.
This, on the other hand, indicates to me that you are not connecting to your db when you directly execute seed_shipment - in fact, you seem to reference something different (as you write). In other words, db = MySQL() is not called.
I recommend that you try the following.
# project\__init__.py
from flask import Flask, g
from flask_mysqldb import MySQL
from .config import app_config
def create_app(config_name):
app = Flask(__name__,
instance_path=os.path.join(os.path.dirname(__file__), 'instance'),
instance_relative_config=True)
app.config.from_object(app_config[config_name])
# this here is just to register the teardown context and some variables ....
MySQL(app)
return app
def get_db():
if 'db' not in g:
g.db = MySQL().connection.cursor()
return g.db
That way, MySQL(app) is always executed when you call create_app. Now, you should be able to simply call get_db each time you want your db.

I have created a database on pythoneverywhere.com and I want to use it locally, in visual studio code project

I cannot connect to my pythoneverywhere.com database from my local project.
The error is:
mysql.connector.errors.InterfaceError: 2013: Lost connection to MySQL server during query
Thank you in advance!
from flask import Flask, request, url_for, redirect
from flask_restful import Resource, Api
import pymysql as MySQLdb
from flaskext.mysql import MySQL
import mysql.connector
import sshtunnel
app = Flask(__name__)
api = Api(app)
sshtunnel.SSH_TIMEOUT = 5.0
sshtunnel.TUNNEL_TIMEOUT = 5.0
with sshtunnel.SSHTunnelForwarder(
('ssh.pythonanywhere.com'),
ssh_username='XXX', ssh_password='XXX',
remote_bind_address=('bianca.mysql.pythonanywhere-services.com', 3306)
) as tunnel:
connection = mysql.connector.connect(
user='XXX', password='XXX',
host='127.0.0.1', port=tunnel.local_bind_port,
database='bianca$moviesdb',
)
connection.close()
# print('after SSH connection')
conn = MySQLdb.connect("bianca.mysql.pythonanywhere-services.com", "XXX", "XXX", "bianca$moviesdb")
c = conn.cursor()
c.execute("SELECT * FROM reviews")
rows = c.fetchall()
for eachRow in rows:
print(eachRow)
if __name__ == '__main__':
app.run(port=5002)
Many things could be happening here: Timeout errors, packet sizes, etc. Also check your firewall settings.
https://dev.mysql.com/doc/refman/5.7/en/error-lost-connection.html

Connect to MSSQL Database using Flask-SQLAlchemy

I'm trying to connect to a local MSSQL DB through Flask-SQLAlchemy.
Here's a code excerpt from my __init__.py file:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mssql+pyodbc://HARRISONS-THINK/LendApp'
db = SQLAlchemy(app)
SQLALCHEMY_TRACK_MODIFICATIONS = False
As you can see in SQL Server Management Studio, this information seems to match:
Here is the creation of a simple table in my models.py file:
from LendApp import db
class Transaction(db.model):
transactionID = db.Column(db.Integer, primary_key=True)
amount = db.Column(db.Integer)
sender = db.Column(db.String(80))
receiver = db.Column(db.String(80))
def __repr__(self):
return 'Transaction ID: {}'.format(self.transactionID)
I am then connecting to the database using a Python Console within Pycharm via the execution of these two lines:
>>> from LendApp import db
>>> db.create_all()
This is resulting in the following error:
DBAPIError: (pyodbc.Error) ('IM002', '[IM002] [Microsoft][ODBC Driver Manager] Data source name not found and no default driver specified (0) (SQLDriverConnect)')
The only thing that I can think of is that my database connection string is incorrect. I have tried altering it to more of a standard Pyodbc connection string and including driver={SQL SERVER} but to no prevail.
If anyone could help me out with this it would be highly appreciated.
Thanks
So I just had a very similar problem and was able to solve by doing the following.
Following the SQL Alchemy documentation I found I could use the my pyodbc connection string like this:
# Python 2.x
import urllib
params = urllib.quote_plus("DRIVER={SQL Server Native Client 10.0};SERVER=dagger;DATABASE=test;UID=user;PWD=password")
engine = create_engine("mssql+pyodbc:///?odbc_connect=%s" % params)
# Python 3.x
import urllib
params = urllib.parse.quote_plus("DRIVER={SQL Server Native Client 10.0};SERVER=dagger;DATABASE=test;UID=user;PWD=password")
engine = create_engine("mssql+pyodbc:///?odbc_connect=%s" % params)
# using the above logic I just did the following
params = urllib.parse.quote_plus('DRIVER={SQL Server};SERVER=HARRISONS-THINK;DATABASE=LendApp;Trusted_Connection=yes;')
app.config['SQLALCHEMY_DATABASE_URI'] = "mssql+pyodbc:///?odbc_connect=%s" % params
This then caused an additional error because I was also using Flask-Migrate and apparently it doesn't like % in the connection URI. So I did some more digging and found this post. I then changed the following line in my ./migrations/env.py file
From:
from flask import current_app
config.set_main_option('sqlalchemy.url',
current_app.config.get('SQLALCHEMY_DATABASE_URI'))
To:
from flask import current_app
db_url_escaped = current_app.config.get('SQLALCHEMY_DATABASE_URI').replace('%', '%%')
config.set_main_option('sqlalchemy.url', db_url_escaped)
After doing all this I was able to do my migrations and everything seems as if it is working correctly now.
If someone still stumbled upon this issue and trying to figure out another solution then try with pymssql instead of pyodbc;
pip install pymssql
Connection URI would be:
conn_uri = "mssql+pymssql://<username>:<password>#<servername>/<dbname>"
I just changed my connection string something like this and its worked perfectly
NOTE: you need to install pyodbc to work....
app.config["SQLALCHEMY_DATABASE_URI"] = "mssql+pyodbc://user:pwd#server/database?driver=SQL+Server"
Note:
Try to avoid '#' character in password. you will get error because connection string also has '#' character after password. This also can cause the connection error
I had the same problem, it was resolved by specifying:
app = Flask(__name__)
app.config["SQLALCHEMY_DATABASE_URI"] = "mssql+pyodbc://MySQLServerName/MyTestDb?driver=SQL+Server?trusted_connection=yes"
app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False
db.init_app(app)
using below solution i get resolve my connection issue with MSSQL server
params = urllib.parse.quote_plus('DRIVER={SQL Server};SERVER=HARRISONS-THINK;DATABASE=LendApp;Trusted_Connection=yes;')
app.config['SQLALCHEMY_DATABASE_URI'] = "mssql+pyodbc:///?odbc_connect=%s" % params
If you are getting any Login failed for User error then please go to this
http://itproguru.com/expert/2014/09/how-to-fix-login-failed-for-user-microsoft-sql-server-error-18456-step-by-step-add-sql-administrator-to-sql-management-studio/.
I believe your connection string is missing the authentication details. From Flask-SQLAlchemy documentation, the connection string should have the following format
dialect+driver://username:password#host:port/database
From your example, I believe it will look something like this
app.config['SQLALCHEMY_DATABASE_URI'] = 'mssql+pyodbc://<username>:<password>#<Host>:<Port>/LendApp'

Flask-MySQL - commands out of sync

I'm having issues with reading data out of mysql with a cursor and displaying it over HTTP via flask. Everytime I run this code:
import os
from flask import Flask, request, session, url_for, redirect, \
render_template, abort, g, flash, _app_ctx_stack
from flaskext.mysql import MySQL
from contextlib import closing
from hashlib import md5
from datetime import datetime
import time
import os
from werkzeug import check_password_hash, generate_password_hash
import config
app = Flask(__name__)
mysql = MySQL()
app.config['MYSQL_DATABASE_HOST'] = config.MYSQL_DATABASE_HOST
app.config['MYSQL_DATABASE_PORT'] = config.MYSQL_DATABASE_PORT
app.config['MYSQL_DATABASE_USER'] = config.MYSQL_DATABASE_USER
app.config['MYSQL_DATABASE_PASSWORD'] = config.MYSQL_DATABASE_PASSWORD
app.config['MYSQL_DATABASE_DB'] = config.MYSQL_DATABASE_DB
mysql.init_app(app)
if 'SECRET_KEY' in os.environ:
app.config['SECRET_KEY'] = os.environ['SECRET_KEY']
else:
app.config['SECRET_KEY'] = os.urandom(24)
###
# Routing for your application.
###
def init_db():
with closing(connect_db()) as db:
with app.open_resource('init.sql') as f:
db.cursor().execute(f.read())
db.commit()
def connect_db():
return mysql.connect()
if __name__ == '__main__':
init_db()
app.run(debug=True)
I get this result:
(venv)λ fh → λ git master* → python app.py
Exception _mysql_exceptions.ProgrammingError: (2014, "Commands out of sync; you can't ru
n this command now") in <bound method Cursor.__del__ of <MySQLdb.cursors.Cursor object a
t 0x10bc3ddd0>> ignored
Traceback (most recent call last):
File "app.py", line 124, in <module>
init_db()
File "app.py", line 38, in init_db
db.commit()
_mysql_exceptions.ProgrammingError: (2014, "Commands out of sync; you can't run this com
mand now")
Any ideas? I'm new to flask.
Seems you need to start the app before trying to do your DB stuff, as you are accessing the DB through Flask. I'm not experienced with Flask, so I'm not sure how you can access the DB after starting the server, but I can look if you don't know. Basically,
init_db()
app.run(debug=True)
needs to be reversed to
app.run(debug=True)
init_db()
In some way.

Categories

Resources