pythonsql-serverdjangopyodbc

Using external SQL Server database in Django


I'm trying to make a Django website that connects to an external SQL Server database to retrieve information only (read-only). This database is huge with hundreds of tables.

I can currently get it to work by creating a function in my Django app that uses the connectionString and runs a raw SQL query and returns it in a pandas dataframe.

Somehow I feel this is not how Django should be used. Can you please guide me on how to do this in the proper Django way. I think I need to use models? but this is an external database and I don't want to write anything to it. I also don't want to have to define all the table names in my models, but I will if I have to. Can you please guide me on how to go about this while making sure the database stays as read-only?

How do I structure my settings.py, how do I structure my models.py, how do I structure my views.py to be able to interact with the database?

import pyodbc
import pandas as pd

def SQL_to_df(driver,server,database,user,password,query):
    connectionString = pyodbc.connect(f"Driver={driver};Server{server};Database={database};UID={user};PWD={password};")
    df = pd.read_sql(query, connectionString)
    return df

Solution

  • So I figured out how to do this. Basically you can add an external database in your settings file and in order to ensure I didn't write any changes to it I used a library called django-db-readonly. It prevents writing to any database so this is my settings.py file

    #db read only setting
    SITE_READ_ONLY = True
    DB_READ_ONLY_DATABASES = ['external_db']
    
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.sqlite3',
            'NAME': BASE_DIR / 'db.sqlite3',
        },
        'external_db': {
            'ENGINE': 'mssql',
            'NAME': os.environ['DB_NAME'],
            'USER': os.environ['USER'],
            'PASSWORD': os.environ['PASSWD'],
            'HOST': os.environ['HOST'],
            'PORT': '1433',
            'OPTIONS': {
                'driver': 'ODBC Driver 17 for SQL Server',
                'extra_params': 'Encrypt=no;TrustServerCertificate=yes;'
            }
        }
    }
    

    Then in my views.py file you could do the following, in my case, I wanted to get my results as a pandas dataframe, but you could get the SQL results any way you choose

    from django.db import connections
    import pandas as pd
    
    query = "SELECT * FROM table"
    
    with connections[external_db].cursor() as cursor:
            df = pd.read_sql(query, con=connections[external_db].connection)