Django在多个数据库中复制表格

huangapple go评论62阅读模式
英文:

Django duplicate tables with multiple databases

问题

我有多个数据库,一个是sqlite,其他的是postgresql,都在同一个应用程序中使用。当我执行数据库迁移时,所有在models.py中定义的表都会在所有数据库中创建,包括sqlite数据库,或者如果我在allow_migrate函数中添加return False,则什么都不会发生。

如何阻止出现重复的表格?

这是我的代码:

settings.py

DATABASE_ROUTERS = ['routers.router.sqlite_Router','routers.router.postgres_router_1','routers.router.postgres_router_2']

DATABASES = {
    'default': {},
    'auth_db': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    },
    'postgres_db_1': {
        'ENGINE': 'django.db.backends.postgresql',
        'OPTIONS': {
            'options': '-c search_path=test'
        },
        'NAME': 'test1',
        'USER': 'postgres',
        'PORT':'5432',
        'PASSWORD': 'postgres',
        'HOST':'localhost',
    },
    'postgres_db_2': {
        'ENGINE': 'django.db.backends.postgresql',
        'OPTIONS': {
            'options': '-c search_path=test'
        },
        'NAME': 'test2',
        'USER': 'postgres',
        'PORT':'5432',
        'PASSWORD': 'postgres',
        'HOST':'localhost',
    }
}

router.py

class sqlite_Router:
    route_app_labels = {'auth', 'contenttypes','admin','sessions'}
    database = 'auth_db'
    # ...
    def allow_migrate(self, db, app_label, model_name=None, **hints):
        model = hints.get('model')
        if model:
            usedb = getattr(model._meta, 'database', None)
            if app_label in self.route_app_labels and usedb == self.database:
                return db == self.database # True
            # else: return False # <= I only get django_migrations, no other tables
        return None

class postgres_router_1:
    route_app_labels = {'test'}
    database = 'postgres_db_1'
    # ...
    def allow_migrate(self, db, app_label, model_name=None, **hints):
        model = hints.get('model')
        if model:
            usedb = getattr(model._meta, 'database', None)
            if app_label in self.route_app_labels and usedb == self.database:
                return db == self.database # True
            # else: return False # <= I only get django_migrations, no other tables
        return None

class postgres_router_2:
    route_app_labels = {'test'}
    database = 'postgres_db_2'
    # ...
    def allow_migrate(self, db, app_label, model_name=None, **hints):
        model = hints.get('model')
        if model:
            usedb = getattr(model._meta, 'database', None)
            if app_label in this.route_app_labels and usedb == this.database:
                return db == this.database # True
            # else: return False # <= I only get django_migrations, no other tables
        return None

models.py

from django.db import models
models.options.DEFAULT_NAMES = models.options.DEFAULT_NAMES + ('database', )

class postgres_one_test(models.Model):
    postgres_test_one = models.CharField(unique=True, max_length=30)
    def __str__(self):
        return self.postgres_test_one
    class Meta:
        app_label = 'test'
        database = 'postgres_db_1'

class postgres_two_test(models.Model):
    postgres_test_two = models.CharField(unique=True, max_length=30)
    def __str__(self):
        return self.postgres_test_two
    class Meta:
        app_label = 'test'
        database = 'postgres_db_2'
# ...

请注意,Meta类中的database属性指定了每个模型属于哪个数据库。在路由器中,您使用allow_migrate方法来控制哪些应用程序可以迁移到哪个数据库。根据您的配置,每个路由器只应用于特定的应用程序,并将其迁移到相应的数据库。确保您的路由器和模型的配置正确无误,这样您就可以避免重复创建表格。

英文:

I have multiple databases one is sqlite and the others in postgresql using one app, when i migrate bases 'using routers' all the tables in models.py gets created in all the bases including sqlite or nothing if i added return false to the allow_migrate function.

how to stop duplicate tables from happening ??

this is my code 'example'

settings.py

DATABASE_ROUTERS = [&#39;routers.router.sqlite_Router&#39;,&#39;routers.router.postgres_router_1&#39;,&#39;routers.router.postgres_router_2&#39;]

DATABASES = {
    &#39;default&#39;: {},
    &#39;auth_db&#39;: {
        &#39;ENGINE&#39;: &#39;django.db.backends.sqlite3&#39;,
        &#39;NAME&#39;: BASE_DIR / &#39;db.sqlite3&#39;,
    },
    &#39;postgres_db_1&#39;: {
        &#39;ENGINE&#39;: &#39;django.db.backends.postgresql&#39;,
        &#39;OPTIONS&#39;: {
            &#39;options&#39;: &#39;-c search_path=test&#39;
        },
        &#39;NAME&#39;: &#39;test1&#39;,
        &#39;USER&#39;: &#39;postgres&#39;,
        &#39;PORT&#39;:&#39;5432&#39;,
        &#39;PASSWORD&#39;: &#39;postgres&#39;,
        &#39;HOST&#39;:&#39;localhost&#39;,
    },
    &#39;postgres_db_2&#39;: {
        &#39;ENGINE&#39;: &#39;django.db.backends.postgresql&#39;,
        &#39;OPTIONS&#39;: {
            &#39;options&#39;: &#39;-c search_path=test&#39;
        },
        &#39;NAME&#39;: &#39;test2&#39;,
        &#39;USER&#39;: &#39;postgres&#39;,
        &#39;PORT&#39;:&#39;5432&#39;,
        &#39;PASSWORD&#39;: &#39;postgres&#39;,
        &#39;HOST&#39;:&#39;localhost&#39;,
    }
}

router.py

class sqlite_Router:
    route_app_labels = {&#39;auth&#39;, &#39;contenttypes&#39;,&#39;admin&#39;,&#39;sessions&#39;}
    database = &#39;auth_db&#39;
    ....
    def allow_migrate(self, db, app_label, model_name=None, **hints):
        model = hints.get(&#39;model&#39;)
        if model:
            usedb = getattr(model._meta, &#39;database&#39;, None)
            if app_label in self.route_app_labels and usedb == self.database:
                return db == self.database # True
            #else: return False # &lt;== i only get django_migrations, no other tables
        return None

class postgres_router_1:
    route_app_labels = {&#39;test&#39;}
    database = &#39;postgres_db_1&#39;
    ....
    def allow_migrate(self, db, app_label, model_name=None, **hints):
        model = hints.get(&#39;model&#39;)
        if model:
            usedb = getattr(model._meta, &#39;database&#39;, None)
            if app_label in self.route_app_labels and usedb == self.database:
                return db == self.database # True
            #else: return False # &lt;== i only get django_migrations, no other tables
        return None

class postgres_router_2:
    route_app_labels = {&#39;test&#39;}
    database = &#39;postgres_db_2&#39;
    ....
    def allow_migrate(self, db, app_label, model_name=None, **hints):
        model = hints.get(&#39;model&#39;)
        if model:
            usedb = getattr(model._meta, &#39;database&#39;, None)
            if app_label in self.route_app_labels and usedb == self.database:
                return db == self.database # True
            #else: return False # &lt;== i only get django_migrations, no other tables
        return None


models.py

from django.db import models
models.options.DEFAULT_NAMES = models.options.DEFAULT_NAMES + (&#39;database&#39;, )
class postgres_one_test(models.Model):
    postgres_test_one = models.CharField(unique=True, max_length=30)
    def __str__(self):
        return self.postgres_test_one
    class Meta:
        app_label = &#39;test&#39;
        database = &#39;postgres_db_1&#39;
.... 


class postgres_two_test(models.Model):
    postgres_test_two = models.CharField(unique=True, max_length=30)
    def __str__(self):
        return self.postgres_test_two
    class Meta:
        app_label = &#39;test&#39;
        database = &#39;postgres_db_2&#39;


...


答案1

得分: 0

找到了一个解决方案。

更改了django.db.models.options

DEFAULT_NAMES中添加了'database'。

在'class Options'的'init'中添加了'self.database = None'。

并将sqlite_router'django apps->allow_migrate'更改为默认值

if app_label in self.route_app_labels:
    return db == self.database
return None

并从allow_migrate中删除'return False'。

还从models中删除了

models.options.DEFAULT_NAMES = models.options.DEFAULT_NAMES + ('database', )

因为它不再需要。其余部分保持不变。

英文:

found A solution.

changed django.db.models.options

added 'database' in the DEFAULT_NAMES

and 'self.database = None' in the 'init' of 'class Options',

and the sqlite_router 'django apps->allow_migrate' to the default

if app_label in self.route_app_labels:
    return db == self.database
return None

and removed the 'return False' from the allow_migrate.

also removed

models.options.DEFAULT_NAMES = models.options.DEFAULT_NAMES + (&#39;database&#39;, )

from models as it's not needed.

everything else is the same

huangapple
  • 本文由 发表于 2023年3月4日 08:22:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/75632881.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定