Python 在Django中只使用一个表使用多个数据库;django_移民”;
对于Django中的项目,我必须使用两个数据库:default和remote。我创建了Python 在Django中只使用一个表使用多个数据库;django_移民”;,python,django,django-models,Python,Django,Django Models,对于Django中的项目,我必须使用两个数据库:default和remote。我创建了routers.py,一切正常 需要在远程数据库上创建一个表,我创建了迁移,运行它,然后创建了表django_migrations。我只希望在默认数据库中有一个表django_migrations Operations to perform: Apply all migrations: admin, auth, contenttypes, sessions Running migrations: App
routers.py
,一切正常
需要在远程数据库上创建一个表,我创建了迁移,运行它,然后创建了表django_migrations
。我只希望在默认数据库中有一个表django_migrations
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying sessions.0001_initial... OK
routers.py
的相关部分如下:
class MyRouter(object):
# ...
def allow_migrate(self, db, app_label, model_name=None, **hints):
if app_label == 'my_app':
return db == 'remote'
return None
我按如下方式运行迁移:
python manage.py migrate my_app --database=remote
python manage.py migrate --database=default
python manage.py migrate --database=remote
现在当我这样做的时候:
python manage.py runserver
我得到以下警告:
您有1个未应用的迁移。您的项目可能无法正常工作,除非您为应用程序(my_应用程序)应用迁移。运行“python manage.py migrate”以应用它们
my_app
的表是在remote
数据库中创建的,而在django_migrations
数据库的remote
中,迁移被标记为已应用
编辑:如何强制Django只使用一个表
Django_迁移
,但仍将迁移应用到不同的数据库中
如何在不同的数据库中应用迁移以避免出现警告?感谢对我的问题的评论,我做了一些研究并得出了以下发现 使用多个数据库会导致在使用迁移时创建一个表
django_migrations
。正如来自的注释所解释的那样,没有选项只在一个表中记录迁移django_migrations
。读取文件后,这一点很清楚
我将用项目中的一个项目foo
和一个应用程序bar
来说明一个示例。应用程序bar
只有一个型号Baz
我们创建项目:
django-admin startproject foo
现在,我们在主项目目录中有以下内容:
- foo
- manage.py
mkdir foo/bar
python manage.py bar foo/bar
我习惯将项目目录中的所有应用分组:
- foo
- manage.py
mkdir foo/bar
python manage.py bar foo/bar
在文件foo/settings.py
中,我们调整设置以使用两个不同的数据库,在本例中,我们使用sqlite3
:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db1.sqlite3'),
},
'remote': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db2.sqlite3'),
}
}
现在我们运行迁移:
python manage.py migrate --database=default
python manage.py makemigrations bar
这将运行所有迁移,部分--database=default
是可选的,因为如果未指定,Django将使用默认数据库
Operations to perform:
Apply all migrations: admin, auth, contenttypes, sessions
Running migrations:
Applying contenttypes.0001_initial... OK
Applying auth.0001_initial... OK
Applying admin.0001_initial... OK
Applying admin.0002_logentry_remove_auto_add... OK
Applying admin.0003_logentry_add_action_flag_choices... OK
Applying contenttypes.0002_remove_content_type_name... OK
Applying auth.0002_alter_permission_name_max_length... OK
Applying auth.0003_alter_user_email_max_length... OK
Applying auth.0004_alter_user_username_opts... OK
Applying auth.0005_alter_user_last_login_null... OK
Applying auth.0006_require_contenttypes_0002... OK
Applying auth.0007_alter_validators_add_error_messages... OK
Applying auth.0008_alter_user_username_max_length... OK
Applying auth.0009_alter_user_last_name_max_length... OK
Applying auth.0010_alter_group_name_max_length... OK
Applying auth.0011_update_proxy_permissions... OK
Applying sessions.0001_initial... OK
将应用程序bar
注册到INSTALLED_APPS
(foo/settings.py
)并创建迁移:
python manage.py migrate --database=default
python manage.py makemigrations bar
在运行迁移之前,我们在栏
应用程序中创建路由器.py
:
class BarRouter(object):
def db_for_read(self, model, **hints):
if model._meta.app_label == 'bar':
return 'remote'
return None
def db_for_write(self, model, **hints):
if model._meta.app_label == 'bar':
return 'remote'
return None
def allow_relation(self, obj1, obj2, **hints):
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
if app_label == 'bar':
return db == 'remote'
if db == 'remote':
return False
return None
现在最简单的方法是将bar
迁移到remote
数据库:
1 contenttypes 0001_initial 2019-11-13 16:51:04.767382
2 auth 0001_initial 2019-11-13 16:51:04.792245
3 admin 0001_initial 2019-11-13 16:51:04.827454
4 admin 0002_logentr 2019-11-13 16:51:04.846627
5 admin 0003_logentr 2019-11-13 16:51:04.864458
6 contenttypes 0002_remove_ 2019-11-13 16:51:04.892220
7 auth 0002_alter_p 2019-11-13 16:51:04.906449
8 auth 0003_alter_u 2019-11-13 16:51:04.923902
9 auth 0004_alter_u 2019-11-13 16:51:04.941707
10 auth 0005_alter_u 2019-11-13 16:51:04.958371
11 auth 0006_require 2019-11-13 16:51:04.965527
12 auth 0007_alter_v 2019-11-13 16:51:04.981532
13 auth 0008_alter_u 2019-11-13 16:51:05.004149
14 auth 0009_alter_u 2019-11-13 16:51:05.019705
15 auth 0010_alter_g 2019-11-13 16:51:05.037023
16 auth 0011_update_ 2019-11-13 16:51:05.054449
17 sessions 0001_initial 2019-11-13 16:51:05.063868
python manage.py migrate bar --database=remote
1 bar 0001_initial 2019-11-13 17:32:39.701784
当我们运行时:
python manage.py runserver
将发出以下警告:
您有1个未应用的迁移。您的项目可能无法正常工作
在您为应用程序应用迁移之前:栏。运行“python manage.py migrate”以应用它们 不过一切似乎都很好。然而,有这样的警告并不令人满意 正确的方法是按照本文的建议为每个数据库运行所有迁移 它看起来是这样的:
python manage.py migrate my_app --database=remote
python manage.py migrate --database=default
python manage.py migrate --database=remote
在为条创建迁移后:
python manage.py migrate bar --database=default
python manage.py migrate bar --database=remote
路由器将注意表bar_baz
仅在remote
数据库中创建,但Django将标记两个数据库中应用的迁移。此外,auth
、admin
、会话
等的表格将仅在默认
数据库中创建,如routers.py
中所述。remote
数据库中的表django_migrations
也将包含这些迁移的记录
这是一篇很长的文章,但我希望它能对这一问题有所启发。我认为,官方并没有对这一问题进行透彻的解释。对于其他非“我的应用”,allow\u migrate没有返回任何结果。也许你想在那里再做一次检查?据我从你的路由器了解,“我的应用程序”使用“远程”数据库,而所有其他应用程序将使用“默认”数据库?@cezar你要求的几乎是不可能的。为了共享django_迁移
表,需要区分迁移为default
和remote
db的行。这在django内部相当深入。我甚至会冒险说,这将需要对迁移代码进行重大重写。@KamilNiski感谢您分享您的想法。我将改写这个问题。可能是相关的。