Я открою с " Вы не должны редактировать настройки во время выполнения ".
Сказав это, у меня точно такая же проблема, где я хочу создать уникальную базу данных для каждого пользователя. Причина для этого заключается в том, что я предоставляю пользователю возможность сохранять / получать доступ к базе данных, не хранящейся на моем сервере, или получать к ней доступ, что предполагает наличие нескольких баз данных, и, следовательно, по одной для каждого пользователя.
Этот ответ НЕ является рекомендуемым способом достижения желаемой цели. Я хотел бы услышать от Джанго-гуру, как лучше всего подойти к этой проблеме. Тем не менее, это решение, которое я использовал, и до сих пор оно работало хорошо. Я использую 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.
Это удобный способ загрузки каждого параметра базы данных, потому что для удаления базы данных из настроек все, что вам нужно сделать, это удалить файл настроек, и при следующем перезапуске сервера он не загрузит эти данные в настройки, и база данных не будет доступна.
Как я уже сказал, это работает, и я до сих пор успешно использовал его, но это НЕ идеальное решение. Я был бы очень признателен, если бы кто-нибудь смог опубликовать лучшее решение.
Что в этом плохого:
- Он явно не поддается совету команды django не изменять настройки во время выполнения. Я не знаю причину, по которой дается этот совет.
- Он использует оператор
exec
для загрузки данных в настройки. Это должно быть хорошо, но если вы получите какой-нибудь поврежденный или вредоносный код в одном из этих файлов, вы будете грустной пандой.
Обратите внимание, что я все еще использую базу данных по умолчанию для данных авторизации и сеансов, но все данные из моих собственных приложений хранятся в пользовательской базе данных.