同一 Django 实例中,如何根据不同的域名配置使用不同的数据库?

偷个懒,不想为不同使用单位单独部署,升级也方便
请大佬给个思路
同一 Django 实例中,如何根据不同的域名配置使用不同的数据库?

12 回复

或者自动部署?


核心思路: 在Django的settings.py中,通过中间件动态修改DATABASES配置,根据请求的域名(request.META['HTTP_HOST'])切换数据库连接。

具体实现:

  1. settings.py中定义多个数据库配置:
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'default_db',
        'USER': 'user',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '5432',
    },
    'domain2_db': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'domain2_database',
        'USER': 'user',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '5432',
    },
    'domain3_db': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'domain3_database',
        'USER': 'user',
        'PASSWORD': 'password',
        'HOST': 'localhost',
        'PORT': '3306',
    }
}
  1. 创建数据库路由中间件: 在项目目录下创建middleware/database_router.py
class DomainDatabaseRouter:
    """根据域名动态选择数据库"""
    
    def __init__(self, get_response):
        self.get_response = get_response
        
    def __call__(self, request):
        # 获取当前请求的域名
        host = request.META.get('HTTP_HOST', '').split(':')[0]
        
        # 定义域名到数据库的映射
        domain_to_db = {
            'www.domain1.com': 'default',
            'api.domain1.com': 'default',
            'www.domain2.com': 'domain2_db',
            'admin.domain2.com': 'domain2_db',
            'www.domain3.com': 'domain3_db',
        }
        
        # 设置当前线程的数据库别名
        from django.db import connections
        db_alias = domain_to_db.get(host, 'default')
        request._state = {'db': db_alias}
        
        # 为所有数据库连接设置当前选择的数据库
        for conn_name in connections:
            connections[conn_name].set_db(db_alias)
        
        response = self.get_response(request)
        return response
  1. 创建数据库路由器: 在项目目录下创建routers.py
class DomainRouter:
    """数据库路由器,配合中间件使用"""
    
    def db_for_read(self, model, **hints):
        from django.db import connections
        # 从当前线程状态获取数据库别名
        for conn in connections.all():
            if hasattr(conn, 'db_alias'):
                return conn.db_alias
        return None
    
    def db_for_write(self, model, **hints):
        from django.db import connections
        for conn in connections.all():
            if hasattr(conn, 'db_alias'):
                return conn.db_alias
        return None
    
    def allow_relation(self, obj1, obj2, **hints):
        # 允许同一数据库内的关系
        return True
    
    def allow_migrate(self, db, app_label, model_name=None, **hints):
        # 只允许向default数据库迁移
        return db == 'default'
  1. 配置中间件和数据库路由:settings.py中添加:
# 添加中间件
MIDDLEWARE = [
    # ... 其他中间件
    'your_project.middleware.database_router.DomainDatabaseRouter',
    # ... 其他中间件
]

# 配置数据库路由
DATABASE_ROUTERS = ['your_project.routers.DomainRouter']
  1. 使用示例:
# 在视图中正常使用ORM,会自动根据域名选择数据库
from myapp.models import MyModel

def my_view(request):
    # 这会自动使用当前域名对应的数据库
    items = MyModel.objects.all()
    return render(request, 'template.html', {'items': items})

关键点说明:

  • 中间件在每个请求开始时根据域名设置数据库别名
  • 数据库路由器确保所有数据库操作都使用正确的连接
  • 迁移操作只针对default数据库,其他数据库需要手动创建表结构

一句话建议: 用中间件+数据库路由的组合方案实现域名到数据库的动态映射。

django orm 可以用 using 选择不同的数据库,配置好多个数据库,根据 request 的请求域名来选择数据库


谢谢提供的思路
https://docs.djangoproject.com/en/2.0/topics/db/multi-db/
我现在知道,在 settings.py 可以提供多个 database 的配置, 在使用中可以 通过 using 来选择切换

现在的配置是 NGINX - uWSGI - Django
不同的实例,用不同的可访问域名和 wsgi.py 。在 wsgi.py 定义 database 的变量(比如 db=‘firstdb’),在后面的 admin.py 或者其他 orm 里面用 using = db 来实现不同的数据库套账

可我不知掉如何访问到 wsgi 里面这个变量 db,或者 using = db 这种方式是否可行?

请指教

既然有不同个 wsgi.py
wsgi.py 有这个 os.environ.setdefault(“DJANGO_SETTINGS_MODULE”, “project.settings”)
你也可以加一个 os.environ.setdefault(“DATABASES”, “db1”)
然后在 settings.py, 使用 os.environ 获取” db1 “
最后 DATABASES = {“default”: MULT_DATABASES[“db1”]}
其中 MULT_DATABASES = {” db1 “:{···},” db2 “:{···}}

这样做的话,就不需要用 using 了

送你 36 个赞

这操作风险略高啊
域名和数据库地址环境变量注入,然后用 docker compose 起,没啥大工作量

细节上略有调整,已部署成功,谢谢!
docker 还没入门,我现在让它跑起来,至少可行。目前只是 demo 而已,重在业务可行性演示。谢谢你的信息

你没看过 django 里自带的 site 框架? https://docs.djangoproject.com/en/2.0/ref/contrib/sites/

你好,终于看到跟我同样问题。一直困扰。看你上面的答案还是我还是不太明白,
wsgi.py 里设置 os.environ.setdefault(“DATABASES”, “db1”)
然后在 settings.py, 如何设置来获取” db1 “呢。
settings.py 里设置 DATABASES = {“default”: MULT_DATABASES[“db1”]}
其中 MULT_DATABASES = {” db1 “:{···},” db2 “:{···}}.
如何根据用户的 ip 或者用户名或者请求的 url 来自动切换切换 db 呢。apps 里面的内容都是相同的(通用的)。想把数据库分开。
楼主能分享详细点吗?感激不尽。


settings.py, 如何设置来获取” db1 "?
–os.environ.get(‘DATABASES’))

回到顶部