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