43

私はdjangoを評価してきましたが、次のことが可能かどうか疑問に思いました。私はすでに通常の複数データベースのドキュメントを見てきましたが、私が理解できる限り、このユースケースについて言及されていないため、それを指摘しないでください。私が間違っていたら、私はそれを取り戻します:)

アプリのモデルのほとんどが存在する 1 つのメイン データベースが必要ですが、アプリの 1 つはデータベースを動的に作成する必要があり、これらは顧客固有のデータベースになります。

データベース パス (私は sqlite を使用する予定です) はプライマリ データベースに格納されるため、カーソルを変更する必要がありますが、モデルは同じままです。

これを達成する方法について何か考えを歓迎しますか?

4

3 に答える 3

38

「実行時に設定を編集しないでください」で開きます。

そうは言っても、ユーザーごとに一意のデータベースを作成したいという、まったく同じ問題があります。これを行う理由は、ユーザーがサーバーに保存されていないデータベースに保存/アクセス/アクセスできる機能を提供しているためです。これには、複数のデータベースが必要であり、ユーザーごとに 1 つ必要です。

この回答は、望ましい目標を達成するための推奨される方法ではありません。この問題への最善のアプローチ方法をジャンゴの第一人者から聞きたいです。ただし、これは私が使用してきたソリューションであり、これまでのところうまく機能しています。私は sqlite を使用していますが、どのデータベースでも簡単に変更できます。

要約すると、これはプロセスです。

  1. 新しいデータベースを設定に追加します (実行時)
  2. サーバーの再起動時 (実行時) に再ロードするために、これらの設定を保存するファイルを作成します。
  3. 保存された設定ファイルをロードするスクリプトを実行します (サーバーが再起動されるたびに)

さて、これを達成する方法:

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) サーバーの起動時にこれらの設定を実際にロードするには、 の一番下に 1 行を追加し/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

このコードを import ステートメントの代わりに settings.py の一番下に直接配置することもできますが、import ステートメントを使用すると、settings.py の抽象化レベルの一貫性が保たれることに注意してください。

これは、設定からデータベースを削除するには、設定ファイルを削除するだけでよいため、各データベース設定を読み込む便利な方法です。次にサーバーを再起動したときに、これらの詳細は設定に読み込まれず、データベースアクセスできなくなります。

私が言ったように、これは機能し、これまでのところ使用に成功していますが、これは理想的なソリューションではありません. 誰かがより良い解決策を投稿できれば、本当に感謝しています。

悪い点:

  • 実行時に設定を変更しないという django チームからのアドバイスに明示的に反対します。なぜこのようなアドバイスが与えられたのか、私にはわかりません。
  • execステートメントを使用して、データを設定にロードします。これは問題ないはずですが、これらのファイルのいずれかに破損したコードや悪意のあるコードが含まれていると、悲しいパンダになります.

認証データとセッション データには引き続き既定のデータベースを使用しますが、独自のアプリのすべてのデータはユーザー固有のデータベースに保存されます。

于 2012-07-02T11:13:39.343 に答える
13

@thedawnrider の回答を補強するには、編集settings.DATABASESだけでは不十分な場合があります。django.db.connections.databasesキャッシュおよびラッパーとして機能する edit の方が信頼性が高い場合があります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
于 2015-03-06T02:29:29.493 に答える