英文:
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 = ['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 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
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'
...
答案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 + ('database', )
from models as it's not needed.
everything else is the same
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论