在 Django 中使用两个数据库(一个只读)

问题描述 投票:0回答:2

我正在使用两个数据库,一个用于读取数据,然后将数据写入另一个数据库。下面是我的路由器类和我对设置的更改,但我对这个概念非常陌生,在这方面有更多经验的人可以确认它应该工作或帮助进行编辑吗?

应用程序名为“myapp”,只读数据库我命名为“readonly_db”,我要写入的数据库是“默认”数据库。

    class MyappRouter:
        def db_for_read(self, model, **hints):
            if model._meta.app_label == 'myapp':
                return 'readonly_db'
            return None
        def db_for_write(self, model, **hints):
            if model._meta.app_label == 'myapp'
                return 'default'
            return None

        def allow_relation(self, obj1, obj2, **hints):
            if obj1._meta.app_label == obj2._meta.app_label:
                return True
            else:
                return False
            return None

        def allow_migrate(self, db, **hints):
            if db == 'default':
                return True
            elif db == 'readonly_db':
                return False
            return None
    DATABASE_ROUTERS = ['<path to>.myapprouter.py']
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql',
            'NAME': 'myapp' ,
            'USER': 'USER',
            'PASSWORD': 'PASSWORD',
            'HOST': 'LOCALHOST',
            'PORT': '5432'
        }
        'readonly_db': {
            'ENGINE': 'django_postgres_readonly'
            'NAME': 'READONLY'
            'USER': 'USER'
            'PASSWORD': 'PASSWORD'
            'HOST': 'LOCALHOST'
            'PORT': '5432'
    }
python django database multiple-databases
2个回答
4
投票

你走的路是对的。我将分享我当前正在运行的解决方案。

设置.py

USE_REPLICA = eval_env_as_boolean("USE_REPLICA", False)

DATABASES = {
    "default": {
        "ENGINE": os.getenv("DB_ENGINE", "django.db.backends.sqlite3"),
        "NAME": os.getenv("DB_DATABASE", os.path.join(BASE_DIR, "db.sqlite3")),
        "USER": os.getenv("DB_USER"),
        "HOST": os.getenv("DB_HOST"),
        "PORT": os.getenv("DB_PORT"),
        "PASSWORD": os.getenv("DB_PASSWORD"),
    }
}

DATABASES["default"]["CONN_MAX_AGE"] = int(os.getenv("DB_CONN_MAX_AGE", 0))  # type: ignore

if USE_REPLICA:
    DATABASES["replica"] = {
        "ENGINE": os.getenv("DB_ENGINE_REPLICA"),
        "NAME": os.getenv("DB_DATABASE_REPLICA"),
        "USER": os.getenv("DB_USER_REPLICA"),
        "HOST": os.getenv("DB_HOST_REPLICA"),
        "PORT": os.getenv("DB_PORT_REPLICA"),
        "PASSWORD": os.getenv("DB_PASSWORD_REPLICA"),
    }

    DATABASES["replica"]["CONN_MAX_AGE"] = int(os.getenv("DEFAULT_DB_CONN_MAX_AGE_REPLICA", 0))  # type: ignore
    DATABASE_ROUTERS = ["my_app.setup.db_routing.DatabaseRouter"]

db_routing.py

class DatabaseRouter:
    """
    A router to control all database operations on models in the
    auth application.
    """

    def db_for_read(self, model, **hints):
        """
        Always read from REPLICA database
        """
        return "replica"

    def db_for_write(self, model, **hints):
        """
        Always write to DEFAULT database
        """
        return "default"

    def allow_relation(self, obj1, obj2, **hints):
        """
        Objects from REPLICA and DEFAULT are de same, then True always
        """
        return True

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        """
        Only DEFAULT database
        """
        return db == "default"

基本上你可以稍微简化你的路由器

更新:

USE_REPLICA
仅作为一个选项存在,因此我可以快速禁用读取数据库。
Settings.py
仅在系统启动时运行,因此系统启动时会添加副本配置,但前提是该变量存在。

关于

CONN_MAX_AGE
,您可以在这里查看更多信息。 这里也在生产清单上。


0
投票

使用这个我收到错误解释如何避免它

© www.soinside.com 2019 - 2024. All rights reserved.