同一 Django 实例中,如何根据不同的域名配置使用不同的数据库?
偷个懒,不想为不同使用单位单独部署,升级也方便
请大佬给个思路
同一 Django 实例中,如何根据不同的域名配置使用不同的数据库?
或者自动部署?
核心思路: 在Django的settings.py中,通过中间件动态修改DATABASES配置,根据请求的域名(request.META['HTTP_HOST'])切换数据库连接。
具体实现:
- 在
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',
}
}
- 创建数据库路由中间件:
在项目目录下创建
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
- 创建数据库路由器:
在项目目录下创建
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'
- 配置中间件和数据库路由:
在
settings.py中添加:
# 添加中间件
MIDDLEWARE = [
# ... 其他中间件
'your_project.middleware.database_router.DomainDatabaseRouter',
# ... 其他中间件
]
# 配置数据库路由
DATABASE_ROUTERS = ['your_project.routers.DomainRouter']
- 使用示例:
# 在视图中正常使用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’))

