我一直在评估 django 并想知道以下是否可行。我已经查看了常规的多数据库文档,所以请不要指出这一点,因为据我所知没有提到这个用例。如果我错了,我把它收回:)
我想要一个主数据库,我的大多数应用程序模型都将驻留在其中,但是其中一个应用程序需要动态创建数据库,这些数据库将是客户特定的数据库。
数据库路径(我计划使用 sqlite)将存储在主数据库中,因此需要更改游标,但模型将保持不变。
我欢迎任何关于如何实现这一目标的想法?
我一直在评估 django 并想知道以下是否可行。我已经查看了常规的多数据库文档,所以请不要指出这一点,因为据我所知没有提到这个用例。如果我错了,我把它收回:)
我想要一个主数据库,我的大多数应用程序模型都将驻留在其中,但是其中一个应用程序需要动态创建数据库,这些数据库将是客户特定的数据库。
数据库路径(我计划使用 sqlite)将存储在主数据库中,因此需要更改游标,但模型将保持不变。
我欢迎任何关于如何实现这一目标的想法?
我将打开“您不应该在运行时编辑设置”。
话虽如此,我有完全相同的问题,我想为每个用户创建一个唯一的数据库。这样做的原因是我为用户提供了保存/访问/访问未存储在我的服务器上的数据库的能力,这需要拥有多个数据库,因此每个用户都有一个。
这个答案不是实现预期目标的推荐方法。我很想听听 django-guru 如何最好地解决这个问题。但是,这是我一直在使用的解决方案,到目前为止效果很好。我正在使用 sqlite,但是可以轻松地为任何数据库修改它。
总而言之,这是一个过程:
现在,如何实现这一点:
1)首先,当创建一个新用户时,我在设置中创建一个新数据库。这段代码在我看来是创建新用户的地方。
from YOUR_PROJECT_NAME import settings
database_id = user.username #just something unique
newDatabase = {}
newDatabase["id"] = database_id
newDatabase['ENGINE'] = 'django.db.backends.sqlite3'
newDatabase['NAME'] = '/path/to/db_%s.sql' % database_id
newDatabase['USER'] = ''
newDatabase['PASSWORD'] = ''
newDatabase['HOST'] = ''
newDatabase['PORT'] = ''
settings.DATABASES[database_id] = newDatabase
save_db_settings_to_file(newDatabase) #this is for step 2)
此脚本“在运行时”将数据库设置加载到 django 项目设置中。但是,如果重新启动服务器,此数据库将不再位于设置中。
2)为了便于在服务器重新启动时自动重新加载这些设置,我为每个数据库创建一个文件,该文件将在服务器启动时加载。创建此文件由函数执行save_db_settings_to_file
:
def save_db_settings_to_file(db_settings):
path_to_store_settings = "/path/to/your/project/YOUR_PROJECT_NAME/database_settings/"
newDbString = """
DATABASES['%(id)s'] = {
'ENGINE': '%(ENGINE)s', # Add 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
'NAME': '%(NAME)s', # Or path to database file if using sqlite3.
'USER': '', # Not used with sqlite3.
'PASSWORD': '', # Not used with sqlite3.
'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
'PORT': '', # Set to empty string for default. Not used with sqlite3.
}
""" % db_settings
file_to_store_settings = os.path.join(path_to_store_settings, db_settings['id'] + ".py")
write_file(file_to_store_settings, newDbString) #psuedocode for compactness
3)为了在服务器启动时实际加载这些设置,我在 的最底部添加了一行/path/to/your/project/YOUR_PROJECT_NAME/settings.py
,它将加载设置文件夹中的每个文件并运行它,具有将数据库详细信息加载到设置中的效果。
import settings_manager
然后,import settings_manager
将在 处加载文件/path/to/your/project/YOUR_PROJECT_NAME/settings_manager.py
,其中包含以下代码:
from settings import DATABASES
import os
path_to_store_settings = "/path/to/your/project/YOUR_PROJECT_NAME/database_settings/"
for fname in os.listdir(path_to_settings):
full_path = os.path.join(path_to_settings, fname)
f = open(full_path)
content = f.read()
f.close()
exec(content) #you'd better be sure that the file doesn't contain anything malicious
请注意,您可以将此代码直接放在 settings.py 的底部而不是 import 语句,但使用 import 语句可以保持 settings.py 的抽象级别一致。
这是加载每个数据库设置的便捷方法,因为要从设置中删除数据库,您只需删除设置文件,下次服务器重新启动时,它不会将这些详细信息加载到设置中,并且数据库将无法访问。
正如我所说,这很有效,到目前为止我已经成功使用它,但这不是理想的解决方案。如果有人可以发布更好的解决方案,我将不胜感激。
有什么不好的:
exec
语句将数据加载到设置中。这应该没问题,但是如果您在其中一个文件中获得了一些损坏或恶意代码,您将是一只可悲的熊猫。请注意,我仍然将默认数据库用于身份验证和会话数据,但我自己的应用程序中的所有数据都存储在用户特定的数据库中。
为了增加@thedawnrider 的答案,在某些情况下编辑settings.DATABASES
可能还不够。编辑可能更可靠django.db.connections.databases
,它充当缓存和包装器settings.DATABASES
。
例如
from django.db import connections
database_id = user.username #just something unique
newDatabase = {}
newDatabase["id"] = database_id
newDatabase['ENGINE'] = 'django.db.backends.sqlite3'
newDatabase['NAME'] = '/path/to/db_%s.sql' % database_id
newDatabase['USER'] = ''
newDatabase['PASSWORD'] = ''
newDatabase['HOST'] = ''
newDatabase['PORT'] = ''
connections.databases[database_id] = newDatabase
这个问题已经过时了,应该更新。
Django 支持开箱即用的多个数据库
Here is many good tutorials [ 1, 2 ] and answers how to manage connections dynamically
Also you may simply use django-dynamic-db-router
Database connection settings may be configured on the fly by using configure
method of settings
object:
from django.conf import settings
dbs = settings.DATABASES.copy()
dbs['some_new_db'] = {'ENGINE': 'dummy'}
settings.configure(DATABASES=dbs)