Подтвердить что ты не робот

Многочисленные и динамические базы данных Django

Я оцениваю django и задаюсь вопросом, возможно ли следующее. Я уже рассмотрел регулярные документы с несколькими базами данных, поэтому, пожалуйста, не указывайте мне это, потому что этот случай использования не упоминается, насколько я могу разобраться. Если я ошибаюсь, я заберу его обратно:)

Мне нужна одна основная база данных, в которой будет находиться большинство моих моделей приложений, однако одному из приложений нужно будет динамически создавать базы данных, это будут базы данных, специфичные для клиента.

Путь к базе данных (я планирую использовать sqlite) будет храниться в первичной базе данных, поэтому курсор нужно будет изменить, но модель останется прежней.

Я бы приветствовал любые мысли о способах достижения этого?

4b9b3361

Ответ 1

Я откроюсь с помощью Вы не должны редактировать настройки во время выполнения.

Сказав это, у меня есть точно такая же проблема, когда я хочу создать уникальную базу данных для каждого пользователя. Причина этого заключается в том, что я предлагаю пользователю возможность сохранять/получать доступ к/из базы данных, не сохраненной на моем сервере, что подразумевает наличие нескольких баз данных и, следовательно, одного для каждого пользователя.

Этот ответ НЕ является рекомендуемым способом достижения желаемой цели. Я хотел бы услышать от джанго-гуру, как наилучшим образом подойти к этой проблеме. Тем не менее, это решение, которое я использую, и он до сих пор работал хорошо. Я использую sqlite, однако его можно легко модифицировать для любой из баз данных.

Таким образом, это процесс:

  • Добавить новую базу данных в настройки (во время выполнения)
  • Создайте файл для сохранения этих параметров для перезагрузки при перезапуске сервера (во время выполнения)
  • Запустите script, который загружает сохраненные файлы настроек (всякий раз, когда сервер перезагружается)

Теперь, как достичь этого:

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)

Этот script загружает параметры базы данных "во время выполнения" в параметры проекта 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

Обратите внимание, что вы можете поместить этот код непосредственно в bottom. settings вместо дескриптора import, но с помощью оператора import сохраняется уровень абстракции settings.py.

Это удобный способ загрузить каждый параметр базы данных, потому что для удаления базы данных из настроек все, что вам нужно сделать, это удалить файл настроек, и в следующий раз, когда сервер перезагрузится, он не будет загружать эти данные в настройки, и база данных не будет доступна.

Как я уже сказал, это работает, и я успешно использовал его до сих пор, но это НЕ идеальное решение. Я был бы очень признателен, если бы кто-нибудь смог опубликовать лучшее решение.

Что плохого в этом:

  • Он явно не советует команде django не изменять настройки во время выполнения. Я не знаю причины, почему этот совет дается.
  • Он использует оператор exec для загрузки данных в настройки. Это должно быть хорошо, но если вы получите какой-то коррумпированный или вредоносный код в одном из этих файлов, вы будете грустным panda.

Обратите внимание, что я по-прежнему использую базу данных по умолчанию для данных auth и session, но все данные из моих собственных приложений хранятся в базе данных, специфичной для пользователя.

Ответ 2

Чтобы увеличить ответ @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