【问题标题】:Django multiple databases (sanity check)Django 多个数据库(健全性检查)
【发布时间】:2017-07-01 12:39:38
【问题描述】:

下午。我已经阅读了很多关于该主题的地方,从每个地方获取信息,因为它们看起来并不完全一致,并且相信我有这个工作。由于这是一个测试设置,我不想花几个月的时间来发现某些东西不起作用 --- 事实证明是这样的。

感谢那些比我更有经验的人看过这个,并请提出任何建议。

settings.py

DATABASES = {
'default': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'myproject',
    'USER': 'myprojectuser',
    'PASSWORD': 'abc123',
    'HOST': 'localhost',
    'PORT': '',
},
'ta1_db': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'testapp1db',
    'USER': 'ta1',
    'PASSWORD': 'ta1',
    'HOST': 'localhost',
    'PORT': '',
},
'ta2_db': {
    'ENGINE': 'django.db.backends.postgresql_psycopg2',
    'NAME': 'testapp2db',
    'USER': 'ta2',
    'PASSWORD': 'ta2',
    'HOST': 'localhost',
    'PORT': '',
},
}

DATABASE_ROUTERS = ['spiderproject.routers.DBRouter',]

routers.py(在主 spiderproject 文件夹中)

class DBRouter(object):

def db_for_read(self, model, **hints):
    """Send all read operations on 'app_label' app models to associated db"""
    if model._meta.app_label == 'testapp1':
        return 'ta1_db'
    if model._meta.app_label == 'testapp2':
        return 'ta2_db'
    return None

def db_for_write(self, model, **hints):
    """Send all write operations on 'app_label' app models to associated db"""
    if model._meta.app_label == 'testapp1':
        return 'ta1_db'
    if model._meta.app_label == 'testapp2':
        return 'ta2_db'
    return None

def allow_relation(self, obj1, obj2, **hints):
    """Determine if relationship is allowed between two objects."""

    # Allow any relation between two models that are in the same app.
    if obj1._meta.app_label == 'testapp1' and obj2._meta.app_label == 'testapp1':
        return True
    if obj1._meta.app_label == 'testapp2' and obj2._meta.app_label == 'testapp2':
        return True
    # No opinion if neither object is in the Example app (defer to default or other routers).
    elif 'testapp1' not in [obj1._meta.app_label, obj2._meta.app_label] and 'testapp2' not in [obj1._meta.app_label, obj2._meta.app_label]:
        return None

    # Block relationship if one object is in the Example app and the other isn't.
        return False

def allow_migrate(self, db, app_label, model_name=None, **hints):
    """Ensure that the 'app_label' app's models get created on the right database."""
    if app_label == 'testapp1':
        return db == 'ta1_db'
    if app_label == 'testapp2':
        return db == 'ta2_db'
    elif db == 'default':
        # Ensure that all other apps don't get migrated on the example_db database.???
        return False

    # No opinion for all other scenarios
    return None

(我不确定 allow_migrate() 中的 elif 是否正确。还有 allow_relation() 中的 elif。我从一个示例中改编了这些)

我已经在他们自己的 admin.py 中注册了 testapp1 和 testapp2 的模型,它们出现在管理页面上——此时添加/删除数据是可以的,我检查它们是独立存储的。

非常感谢。

【问题讨论】:

  • 您的用例是什么?一个常见的方法是存储单个模式的多个副本,例如支持多个客户端,每个客户端都有自己的隔离存储。如果这是你的目标,你可以考虑django-tenants
  • 目前我托管我自己的 Django/gunicorn/nginx 站点,其中一个项目源于需要托管基于 Lightroom 数据库(sqlite3,只读 - 我可能会记录)的应用程序。我的意图是改变网站,保持单一的项目结构,并为不同的事情提供单独的应用程序(添加现有的 Lr)。我知道可以有多个项目并使用 nginx 来路由它们,但我想为每个站点使用应用程序(客户端数量非常少)。可能有不同的 db 类型,我很满意,Postgres 被用作示例,只是为了让路由工作。

标签: python django database router


【解决方案1】:

这是我推荐的路由器。下面用cmets解释


class DBRouter(object):
    def db_for_read(self, model, **hints):
        """Send all read operations on 'app_label' app models to associated db"""
        if model._meta.app_label == 'testapp1':
            return 'ta1_db'
        if model._meta.app_label == 'testapp2':
            return 'ta2_db'
        # return None
        
        # I recommend returning 'default' here since 
        # it is your default database
        return 'default'

    def db_for_write(self, model, **hints):
        """Send all write operations on 'app_label' app models to associated db"""
        if model._meta.app_label == 'testapp1':
            return 'ta1_db'
        if model._meta.app_label == 'testapp2':
            return 'ta2_db'
        # return None
        
        # I recommend returning 'default' here since 
        # it is your default database, this will allow
        # commonly used django apps to create their
        # models in the default database (like contenttypes 
        # and django auth
        return 'default'

    def allow_relation(self, obj1, obj2, **hints):
        """Determine if relationship is allowed between two objects."""

        # Allow any relation between two models that are in the same app.
        # I prefer to make this global by using the following syntax
        return obj1._meta.app_label == obj2._meta.app_label


    def allow_migrate(self, db, app_label, model_name=None, **hints):
        
        # I think this was your biggest misunderstanding
        # the db_for_write will pick the correct DB for the migration
        # allow_migrate will only let you say which apps/dbs you 
        # should not migrate.  I *strongly* recommend not taking
        # the belt and braces approach that you had here.        
        return True

【讨论】:

  • 感谢您的意见。我将拍摄 vm 的快照,并在稍后尝试一下。在尝试之前我必须说,它看起来更合乎逻辑。
猜你喜欢
  • 2011-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-24
  • 2015-04-10
  • 1970-01-01
  • 2021-12-24
相关资源
最近更新 更多