27

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

1
  • Hi all, for the "no default driver specified" I figured in out in my own question, it might be relevant to this: stackoverflow.com/a/51927158/1896134 Commented May 17, 2022 at 22:29

8 Answers 8

25

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.

Sign up to request clarification or add additional context in comments.

Comments

6

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

1 Comment

Thanks, I was misisng the ?driver=SQL+Server
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>"

Comments

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)

Comments

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

Comments

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'

Comments

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

Comments

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.