You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Django中使用外部只读SQL Server数据库的规范实现问询

用Django规范方式连接只读外部SQL Server数据库

1. 多数据库配置(settings.py)

首先在settings.py中配置外部SQL Server数据库(保留原主数据库的同时添加新配置),使用Django官方支持的SQL Server后端:

import os
from pathlib import Path

BASE_DIR = Path(__file__).resolve().parent.parent

DATABASES = {
    'default': {
        # 你的主数据库配置(比如默认的SQLite)
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    },
    'external_mssql': {
        'ENGINE': 'django.db.backends.sqlserver',
        'NAME': os.getenv('EXTERNAL_DB_NAME'),
        'USER': os.getenv('EXTERNAL_DB_USER'),
        'PASSWORD': os.getenv('EXTERNAL_DB_PWD'),
        'HOST': os.getenv('EXTERNAL_DB_HOST'),
        'PORT': '1433',  # SQL Server默认端口,根据实际修改
        'OPTIONS': {
            'driver': 'ODBC Driver 17 for SQL Server',  # 匹配你的ODBC驱动版本
        },
    }
}

注意:需要先安装依赖包:pip install pyodbc django-mssql-backend,并确保系统已安装对应版本的ODBC驱动。

2. 处理数百张表:两种实现方案

方案A:自动生成ORM模型(适合需ORM操作的场景)

如果想用Django ORM进行查询(避免写原生SQL),可以用inspectdb命令自动生成所有外部表的模型:

# 生成模型文件到指定app
python manage.py inspectdb --database=external_mssql > your_app/models_external.py

将生成的模型整合到models.py或单独文件中,需给每个模型添加managed = False(禁止Django修改表结构):

from django.db import models

class ExternalSales(models.Model):
    sale_id = models.IntegerField(primary_key=True)
    product_name = models.CharField(max_length=255)
    sale_date = models.DateTimeField()
    # 其他字段由inspectdb自动生成

    class Meta:
        managed = False
        db_table = 'sales'  # 对应数据库实际表名
        app_label = 'your_app'

之后就可以用ORM查询,还能快速转成Pandas DataFrame:

from .models import ExternalSales
import pandas as pd

# 从外部库查询数据
queryset = ExternalSales.objects.using('external_mssql').filter(sale_date__year=2024)
# 转DataFrame
df = pd.DataFrame(queryset.values())

方案B:用Django连接执行原生SQL(适合灵活查询)

如果不需要定义所有表的模型,直接用Django的数据库连接执行原生SQL,比手动写pyodbc更规范(复用配置、连接池):

# 在utils.py中封装函数
from django.db import connections
import pandas as pd

def sql_to_df(query):
    with connections['external_mssql'].cursor() as cursor:
        cursor.execute(query)
        # 获取列名
        columns = [col[0] for col in cursor.description]
        # 获取数据
        data = cursor.fetchall()
        return pd.DataFrame(data, columns=columns)

调用示例:df = sql_to_df("SELECT TOP 100 * FROM sales WHERE region='North'")

3. 确保数据库只读(双重保障)

核心:数据库用户权限

给SQL Server的连接用户仅授予SELECT权限,禁止INSERT/UPDATE/DELETE/ALTER等操作,这是最根本的只读保障(通过SQL Server管理工具配置)。

Django层面限制

  • 模型设置managed = False,防止Django尝试创建/修改表结构
  • 自定义只读模型管理器,从代码层面禁止写操作:
class ReadOnlyManager(models.Manager):
    def create(self, **kwargs):
        raise NotImplementedError("该数据库为只读,禁止写入")
    
    def update(self, **kwargs):
        raise NotImplementedError("该数据库为只读,禁止更新")
    
    def delete(self):
        raise NotImplementedError("该数据库为只读,禁止删除")

class ExternalSales(models.Model):
    # ...字段
    objects = ReadOnlyManager()
    
    class Meta:
        managed = False
        db_table = 'sales'

4. views.py示例

ORM查询示例

from django.shortcuts import render
from .models import ExternalSales
import pandas as pd

def sales_dashboard(request):
    # 从外部库查询
    queryset = ExternalSales.objects.using('external_mssql').filter(region='North')
    df = pd.DataFrame(queryset.values())
    # 转HTML表格传给模板
    html_table = df.to_html(classes='table table-striped')
    return render(request, 'sales/dashboard.html', {'sales_table': html_table})

原生SQL查询示例

from django.shortcuts import render
from .utils import sql_to_df

def custom_report(request):
    query = """
        SELECT region, COUNT(sale_id) as total_sales
        FROM sales
        WHERE sale_date BETWEEN '2024-01-01' AND '2024-06-30'
        GROUP BY region
    """
    df = sql_to_df(query)
    html_table = df.to_html()
    return render(request, 'reports/custom.html', {'report_table': html_table})

对比原实现的优势

  • 统一用settings.py管理数据库配置,避免硬编码敏感信息(可结合环境变量)
  • 复用Django的连接池,提升性能
  • 支持ORM和原生SQL两种方式,适配不同场景
  • 更符合Django生态,便于团队维护和扩展

内容的提问来源于stack exchange,提问作者spg719

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 21:22:23