我需要为Django项目设置默认的数据库模式,以便所有应用程序(包括第三方应用程序)的所有表都将其表存储在配置的PostgreSQL模式中。
其中一个解决方案是使用数据库连接选项,例如:
这适用于直接连接到PostgreSQL,但在连接到 PgBouncer(使用连接池)时失败,并显示
另一种在不使用启动参数的情况下设置模式的解决方案是,在所有表名前加上模式前缀。为了确保这对内置和第三方应用程序也有效(而不仅仅是我的应用程序),一个解决方案是在Django加载所有模型时,使用class_prepared信号和一个
这也适用于连接池,但与 Django 迁移不兼容。 使用此解决方案,
我很想知道解决这个问题的正确方法是什么。
其中一个解决方案是使用数据库连接选项,例如:
# in Django settings module add "OPTIONS" to default DB, specifying "search_path" for the connection
DB_DEFAULT_SCHEMA = os.environ.get('DB_DEFAULT_SCHEMA', 'public') # use postgresql default "public" if not overwritten
DATABASES['default']['OPTIONS'] = {'options': f'-c search_path={DB_DEFAULT_SCHEMA}'}
这适用于直接连接到PostgreSQL,但在连接到 PgBouncer(使用连接池)时失败,并显示
OperationalError: unsupported startup parameter: options"
。目前看来,PgBouncer 无法识别options
作为启动参数。另一种在不使用启动参数的情况下设置模式的解决方案是,在所有表名前加上模式前缀。为了确保这对内置和第三方应用程序也有效(而不仅仅是我的应用程序),一个解决方案是在Django加载所有模型时,使用class_prepared信号和一个
AppConfig
将模式名称注入到所有模型的db_table
属性中。这种方法与类似于django-db-prefix的项目接近,只需要确保模式名称被正确引用即可。from django.conf import settings
from django.db.models.signals import class_prepared
def set_model_schema(sender, **kwargs):
schema = getattr(settings, "DB_DEFAULT_SCHEMA", "")
db_table = sender._meta.db_table
if schema and not db_table[1:].startswith(schema):
sender._meta.db_table = '"{}"."{}"'.format(schema, db_table)
class_prepared.connect(set_model_schema)
这也适用于连接池,但与 Django 迁移不兼容。 使用此解决方案,
python manage.py migrate
将无法工作,因为 migrate 命令 通过 内省现有表格 确保 django_migrations
表存在,而模型的 db_table
前缀对其没有影响。我很想知道解决这个问题的正确方法是什么。