Django多个动态数据库

时间:2011-07-05 15:41:59

标签: django django-database

我一直在评估django,并想知道以下是否可行。我已经查看了常规的多个数据库文档,所以请不要指出我,因为我的功能并没有提到这个用例。如果我错了,我会收回它:)

我想要一个主要数据库,我的应用程序的大部分模型都将驻留在该数据库中,但是其中一个应用程序需要动态创建数据库,这些数据库将是客户特定的数据库。

数据库路径(我计划使用sqlite)将存储在主数据库中,因此需要更改游标,但模型将保持不变。

我欢迎任何关于如何实现这一目标的想法?

2 个答案:

答案 0 :(得分:29)

我将打开“You should not edit settings at runtime”。

话虽如此,我也有同样的问题,我想为每个用户创建一个唯一的数据库。这样做的原因是我为用户提供了保存/访问未存储在我的服务器上的数据库的能力,这需要拥有多个数据库,因此每个用户都有一个数据库。

此答案不是实现预期目标的推荐方法。我很想听听django-guru如何最好地解决这个问题。但是,这是我一直在使用的解决方案,到目前为止它运作良好。我正在使用sqlite,但它可以很容易地修改为任何数据库。

总之,这是一个过程:

  1. 将新数据库添加到设置(运行时)
  2. 创建一个文件来存储这些设置,以便在重新启动服务器时(在运行时)重新加载
  3. 运行加载已保存设置文件的脚本(每当重新启动服务器时)
  4. 现在,如何实现这个目标:

    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的最底部添加一行,它将每个文件加载到settings文件夹中并运行它,具有加载数据库详细信息进入设置。

    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语句将数据加载到设置中。这应该没问题,但是如果你在其中一个文件中得到一些损坏的或恶意的代码,你将会是一个悲伤的熊猫。

    请注意,我仍然使用默认数据库进行身份验证和会话数据,但我自己的应用程序中的所有数据都存储在用户特定的数据库中。

答案 1 :(得分:8)

为了增加@ 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 的缓存和包装。

e.g。

{{1}}