26

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:

enter image description here

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

Qwerp-Derp
  • 487
  • 7
  • 20
Harrison
  • 5,095
  • 7
  • 40
  • 60
  • Hi all, for the "no default driver specified" I figured in out in my own question, it might be relevant to this: https://stackoverflow.com/a/51927158/1896134 – JayRizzo May 17 '22 at 22:29

8 Answers8

24

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.

Matt Camp
  • 1,448
  • 3
  • 17
  • 38
5

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

AKJ
  • 328
  • 4
  • 14
5

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

Praveen
  • 346
  • 1
  • 6
  • 18
2

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)
Alex N
  • 171
  • 1
  • 1
  • 5
2

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

Humayun Ahmad Rajib
  • 1,502
  • 1
  • 10
  • 22
1

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'
GerardoMR
  • 81
  • 3
1

This solution makes a perfect connection string to create database connection using flask-sqlalchemy python which can handle password containing special characters.

# Make sure to replace below data with your DB values
DATABASE_HOST = "10.10.10.110"
DATABASE_NAME = "dbtest"
DATABASE_USERNAME = "admin" 
DATABASE_PASSWORD = "admin@123"

# to elimate the error, if the password contains special characters like '@'
DATABASE_PASSWORD_UPDATED = urllib.parse.quote_plus(DATABASE_PASSWORD)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mssql+pymssql://'+DATABASE_USERNAME+':'+DATABASE_PASSWORD_UPDATED+'@'+DATABASE_HOST+'/'+DATABASE_NAME

The code snippet is tired and tested sample to create database connection using flask-sqlalchemy python. Providing database

import os, sys, click, urllib
from flask import Flask, jsonify, request
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text

# Make sure to replace below data with your DB values
DATABASE_HOST = "10.10.10.110"
DATABASE_NAME = "dbtest"
DATABASE_USERNAME = "admin" 
DATABASE_PASSWORD = "admin@123"

app = Flask(__name__)

# to elimate the error, if the password contains special characters like '@' 
DATABASE_PASSWORD_UPDATED = urllib.parse.quote_plus(DATABASE_PASSWORD)
app.config['SQLALCHEMY_DATABASE_URI'] = 'mssql+pymssql://'+DATABASE_USERNAME+':'+DATABASE_PASSWORD_UPDATED+'@'+DATABASE_HOST+'/'+DATABASE_NAME
app.config['SQLALCHEMY_ECHO'] = True
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

# check if the connection is successfully established or not
with app.app_context():
    try:
        # db.session.execute('SELECT 1')
        db.session.execute(text('SELECT 1'))
        print('\n\n----------- Connection successful !')
    except Exception as e:
        print('\n\n----------- Connection failed ! ERROR : ', e)


class Test(db.Model):
    __tablename__ = 't_test'
    __table_args__ = {'extend_existing': True} # allows you to modify the existing table without raising an error.
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    applicationnumber = db.Column(db.String(15))
    source = db.Column(db.String(50))

    def __init__(self, applicationnumber, source):
        self.applicationnumber = applicationnumber
        self.source = source
        print("Executed __init__ !")


@app.route('/api/test', methods=['POST'])
def insert():
    try:
        applicationnumber = request.json['applicationnumber']
        source = request.json['source']
        
        try:
            t_test_obj = Test(applicationnumber, source)
            db.session.add(t_test_obj)
            db.session.commit()
            print("\nRow commited --------")
            return jsonify({'status': 'success', 'message': 'Values inserted successfully.'}), 201
        except Exception as e :
            error=f"Exception Raised : {e}, errorOnLine: {sys.exc_info()[-1].tb_lineno}, file : {os.path.basename(__file__)}"
            click.secho(error, fg="red")
            return jsonify({'status': 'failure', 'message': f"{error}"}), 500

    except Exception as e:
        db.session.rollback()
        return jsonify({'status': 'error', 'message': str(e)}), 500


if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000, debug=True)


# MSSQL query to create table t_test 
'''
CREATE TABLE t_test(
    [id] [int] IDENTITY(1,1) NOT NULL,
    [applicationnumber] [varchar](50) NOT NULL,
    [source] [varchar](50) NULL
)
'''

# API JSON request
'''
{"applicationnumber": "IM012345",
"source": "ABCD"
}
'''

Nikita Malviya
  • 181
  • 1
  • 2
  • 7
0

Just had this issue as well, this is my solution for that:

    import pyodbc

    conn_str = 'DRIVER={ODBC Driver 17 for SQL Server};' \
                   'SERVER=ServerName;' \
                   'DATABASE=dbName;' \
                   'UID=uid;' \
                   'PWD=pass'
    
        conn = pyodbc.connect(conn_str)

app.config["SQLALCHEMY_DATABASE_URI"] = 'mssql+pyodbc:///?odbc_connect={}'.format(conn_str)

and I had to install and config the ODBC Driver. Download ODBC Driver for SQL Server

ASIn98
  • 1
  • 1