django - Django 中间件将请求/响应路由到数据库模式
问题描述
我目前正在使用 django 中间件来处理使用 URL 对不同 postgresql 模式的请求/响应。我想使用另一个数据库来存储具有相同架构的历史数据:例如 - default_db{customer1 schema} 到 history_db {customer1 schema}。
中间件.py
from tenant.utils import set_tenant_schema_for_request
class TenantMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
set_tenant_schema_for_request(request)
response = self.get_response(request)
return response
utils.py 文件
from django.db import connection
from tenant.models import Tenant
def hostname_from_request(request):
# split on `:` to remove port
return request.get_host().split(":")[0].lower()
def tenant_schema_from_request(request):
hostname = hostname_from_request(request)
tenants_map = get_tenants_map()
return tenants_map.get(hostname)
def set_tenant_schema_for_request(request):
schema = tenant_schema_from_request(request)
print(schema)
with connection.cursor() as cursor:
cursor.execute(f"SET search_path to {schema}")
def get_tenants_map():
connection.cursor().execute(f"SET search_path to public")
sub_domains = Tenant.objects.order_by('id').values_list("sub_domain", flat=True)
schema_names = Tenant.objects.order_by('id').values_list("schema_name", flat=True)
tenants = dict(zip(sub_domains, schema_names))
return tenants
# return {"customer1.example.com": "customer1",
# "customer2.example.com": "customer2",
# "example.com": "public"}
路由器.py 文件
from django.db import models
class HistoryRouter:
history_app = {'history'}
def db_for_read(self, model, **hints):
"""
Attempts to read auth and contenttypes models go to auth_db.
"""
if model._meta.app_label in self.history_app:
return 'history_db'
return None
def db_for_write(self, model, **hints):
"""
Attempts to write auth and contenttypes models go to auth_db.
"""
if model._meta.app_label in self.history_app:
return 'history_db'
return None
def allow_relation(self, obj1, obj2, **hints):
"""
Allow relations if a model in the auth or contenttypes apps is
involved.
"""
if (
obj1._meta.app_label in self.history_app or
obj2._meta.app_label in self.history_app
):
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
Make sure the auth and contenttypes apps only appear in the
'auth_db' database.
"""
if db == 'history_db' and app_label in self.history_app:
print('history_db')
return True
elif db == 'default' and app_label not in self.history_app:
print('default_db')
return True
return False
中间件适用于默认数据库,但不适用于“history_db”。
设置.py 文件
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'my_db',
'USER': 'postgres',
'PASSWORD': 'admin,
'HOST': 'localhost',
'PORT': '5432',
},
'history_db': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'history_db',
'USER': 'postgres',
'PASSWORD': 'admin',
'HOST': 'localhost',
'PORT': '5432',
}
}
DATABASE_ROUTERS = ["tenant.router.HistoryRouter"]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'corsheaders.middleware.CorsMiddleware', # cors headers middleware
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
"tenant.middlewares.TenantMiddleware", # custom middleware for tenants
]
问题 ::我希望将发送到 history_db 的请求发送到相关架构。我的默认数据库有模式 ['customer1', 'customer2', 'default'] 和 history_db 有模式 ['customer1', 'customer2', 'default']
解决方案
推荐阅读
- excel - VBA 错误 - 下标超出范围 - 运行时错误 9
- python - 用 C++ 二进制文件打包 python 和 scipy
- javascript - 一个值的谷歌脚本过滤范围
- android - Android 消息配对错误
- amazon-web-services - 运行测试时 EnvironmentVariableCredentialsProvider 不在提供程序中
- neo4j - 如何将大型 csv 文件加载到 Neo4j
- c# - 从另一个 ViewModel 调用 ViewModel 的属性
- dart - Flutter中的文件列表
- apache-spark - 如何并行处理多个 Spark SQL 查询
- javascript - SemanticUI React 弹出式淡入/淡出