簡體   English   中英

Django 數據庫路由

[英]Django Database Routing

我在 Settings.py 中定義了 3 個數據庫,並在各自的應用程序文件夾中為兩個應用程序定義了路由器。 當我嘗試分別為應用程序運行manage.py migrate --database="app_db"時,它只運行default和第二個數據庫列表項。 如果我更改數據庫列表的順序,它將不會執行最后一個,而只會執行第二個。

設置.py

INSTALLED_APPS = [
    # django apps
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    # my apps
    "cred",
    "dms",
    # third party apps
    "rest_framework",
]


DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "databases/db.sqlite3",
    },
    "dms_db": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "databases/dms.sqlite3",
    },
    "cred_db": {
        "ENGINE": "django.db.backends.sqlite3",
        "NAME": BASE_DIR / "databases/cred.sqlite3",
    },
}

DATABASE_ROUTERS = [
    "dms.routers.DMSRouter",
    "cred.routers.CredRouter",
]

AUTH_USER_MODEL = "cred.User"
CRED_DB_ROUTER = "cred_db"
DMS_DB_ROUTER = "dms_db"

如果我將dms_db放在列表索引 1 中,那么它將遷移但cred_db不會。 如果我將cred_db放在索引 1 處,那么它將遷移但dms_db不會。

信用路由器.py

from django.conf import settings


class CredRouter:
    route_app_labels = ["auth", "cred", "contenttypes"]

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return settings.CRED_DB_ROUTER
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return settings.CRED_DB_ROUTER
        return None

    def allow_relation(self, obj1, obj2, **hints):
        if (
            obj1._meta.app_label in self.route_app_labels
            or obj2._meta.app_label in self.route_app_labels
        ):
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label in self.route_app_labels:
            return db == settings.CRED_DB_ROUTER
        return False

dms.router.py

from django.conf import settings


class DMSRouter:
    route_app_labels = [
        "dms",
    ]

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:  # noqa
            return settings.DMS_DB_ROUTER
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:  # noqa
            return settings.DMS_DB_ROUTER
        return None

    def allow_relation(self, obj1, obj2, **hints):
        if (
            obj1._meta.app_label in self.route_app_labels  # noqa
            or obj2._meta.app_label in self.route_app_labels  # noqa
        ):
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label in self.route_app_labels:
            return db == settings.DMS_DB_ROUTER
        return False

我正在運行什么

遷移文件夾中只有initial_0001.py 所以我猜? 它沒有引起任何問題。 不確定。

manage.py makemigrations 
manage.py migrate
manage.py migrate --database="cred_db"
manage.py migrate --database="dms_db"

所有模型都完全共享這種結構。

class Organization(models.Model):
    name = models.CharField(max_length=255)
    email = models.EmailField()
    codename = models.CharField(max_length=254, unique=True)
    ... 

    objects = models.Manager()

    class Meta:
        verbose_name = _("organization")
        verbose_name_plural = _("organization")

隨着項目的發展,我們將擁有更多的數據庫連接,因為我們將集成我們現有的 Django 應用程序,並且每個應用程序都已經建立了一個專用的數據庫服務器。 所以這個項目將連接到至少 8-10 個不同的數據庫。 對於很多人來說,通過移動手動遷移每個人將是一個問題。

路由器適用於所有數據庫,因此allow_migrateDMSRouter調用dms_db中的cred_db 由於DMSRouter僅允許將表遷移到僅dms應用程序,因此您的其他應用程序表永遠不會遷移。 您需要做的是使用在allow_migrate方法中傳遞的參數db ,如果它不是路由器正在處理的參數,則return None而不是False

Cred.Router.py

class CredRouter:
    route_app_labels = ["auth", "cred", "contenttypes"]

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return settings.CRED_DB_ROUTER
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:
            return settings.CRED_DB_ROUTER
        return None

    def allow_relation(self, obj1, obj2, **hints):
        if (
            obj1._meta.app_label in self.route_app_labels
            or obj2._meta.app_label in self.route_app_labels
        ):
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label in self.route_app_labels:
            return db == settings.CRED_DB_ROUTER
        else if db == settings.CRED_DB_ROUTER:
            return False # Only apps in `route_app_labels` will be migrated to `cred_db`
        return None # Let other routers decide

dms.router.py

from django.conf import settings


class DMSRouter:
    route_app_labels = [
        "dms",
    ]

    def db_for_read(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:  # noqa
            return settings.DMS_DB_ROUTER
        return None

    def db_for_write(self, model, **hints):
        if model._meta.app_label in self.route_app_labels:  # noqa
            return settings.DMS_DB_ROUTER
        return None

    def allow_relation(self, obj1, obj2, **hints):
        if (
            obj1._meta.app_label in self.route_app_labels  # noqa
            or obj2._meta.app_label in self.route_app_labels  # noqa
        ):
            return True
        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):
        if app_label in self.route_app_labels:
            return db == settings.DMS_DB_ROUTER
        else if db == settings.DMS_DB_ROUTER:
            return False # Only apps in `route_app_labels` will be migrated to `dms_db`
        return None # Let other routers decide

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM