Nhờ những bình luận về câu hỏi của tôi, tôi đã thực hiện một số nghiên cứu và đưa ra những phát hiện sau đây.
Sử dụng nhiều cơ sở dữ liệu dẫn đến việc tạo bảng django_migrationskhi di chuyển được sử dụng. Không có tùy chọn để ghi lại các lần di chuyển chỉ trong một bảng django_migrations, như nhận xét từ Kamil Niski giải thích. Điều này là rõ ràng sau khi đọc các tập tin django/db/migrations/recorder.py.
Tôi sẽ minh họa một ví dụ với một dự án foovà một ứng dụng barbên trong dự án. Ứng dụng barnày chỉ có một mô hình Baz.
Chúng tôi tạo ra dự án:
django-admin startproject foo
Bây giờ chúng ta có những nội dung này trong thư mục dự án chính:
- foo
- manage.py
Tôi có thói quen nhóm tất cả các ứng dụng trong thư mục dự án:
mkdir foo/bar
python manage.py bar foo/bar
Trong tệp foo/settings.pychúng tôi điều chỉnh cài đặt để sử dụng hai cơ sở dữ liệu khác nhau, cho mục đích của ví dụ này, chúng tôi sử dụng 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'),
}
}
Bây giờ chúng tôi chạy di chuyển:
python manage.py migrate --database=default
Điều này chạy tất cả các di chuyển, phần --database=defaultlà tùy chọn, vì nếu không chỉ định Django sử dụng cơ sở dữ liệu mặc định.
Các thao tác để thực hiện:
Áp dụng tất cả các lần di chuyển: admin, auth, contenttypes, session
Chạy di chuyển:
Áp dụng nội dung.0001_initial ... OK
Áp dụng auth.0001_initial ... OK
Áp dụng admin.0001_initial ... OK
Áp dụng admin.0002_logentry_remove_auto_add ... OK
Áp dụng admin.0003_logentry_add_action_flag_choices ... OK
Áp dụng contenttypes.0002_remove_content_type_name ... OK
Áp dụng auth.0002_alter_ allow_name_max_length ... OK
Áp dụng auth.0003_alter_user_email_max_length ... OK
Áp dụng auth.0004_alter_user_username_opts ... OK
Áp dụng auth.0005_alter_user_last_login_null ... OK
Áp dụng auth.0006_Vquire_contenttypes_0002 ... OK
Áp dụng auth.0007_alter_validators_add_error_messages ... OK
Áp dụng auth.0008_alter_user_username_max_length ... OK
Áp dụng auth.0009_alter_user_last_name_max_length ... OK
Áp dụng auth.0010_alter_group_name_max_length ... OK
Áp dụng auth.0011_update_proxy_permissions ... OK
Áp dụng phiên.0001_initial ... OK
Django đã áp dụng tất cả các di chuyển vào cơ sở dữ liệu mặc định:
1 nội dung 0001_initial 2019-11-13 16: 51: 04.767382
2 auth 0001_initial 2019-11-13 16: 51: 04.792245
3 quản trị viên 0001_initial 2019-11-13 16: 51: 04.827454
4 quản trị viên 0002_logentr 2019-11-13 16: 51: 04.846627
5 quản trị viên 0003_logentr 2019-11-13 16: 51: 04.864458
6 nội dung 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_Vquire 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 phiên 0001_initial 2019-11-13 16: 51: 05.063868
Bây giờ chúng ta tạo mô hình Baz:
models.py:
from django.db import models
class Baz(models.Model):
name = models.CharField(max_length=255, unique=True)
đăng ký ứng dụng barvào INSTALLED_APPS( foo/settings.py) và tạo chủ đề:
python manage.py makemigrations bar
Trước khi chúng tôi chạy di chuyển, chúng tôi tạo routers.pybên trong barứng dụng:
lớp BarRouter (đối tượng):
def db_for_read (tự, mô hình, ** gợi ý):
if model._meta.app_label == 'bar':
trả lại 'từ xa'
trở về Không
def db_for_write (tự, mô hình, ** gợi ý):
if model._meta.app_label == 'bar':
trả lại 'từ xa'
trở về Không
def allow_relation (self, obj1, obj2, ** gợi ý):
trở về Không
def allow_migrate (self, db, app_label, model_name = Không, ** gợi ý):
if app_label == 'bar':
trả về db == 'từ xa'
nếu db == 'từ xa':
trả về sai
trở về Không
và đăng ký nó trong foo/settings.py:
DATABASE_ROUTERS = ['foo.bar.routers.BarRouter']
Bây giờ cách tiếp cận ngây thơ sẽ là chạy các di chuyển barvào remotecơ sở dữ liệu:
python manage.py migrate bar --database=remote
Các thao tác để thực hiện:
Áp dụng tất cả các lần di chuyển: thanh
Chạy di chuyển:
Áp dụng thanh.0001_initial ... OK
Việc di chuyển đã được áp dụng cho remotecơ sở dữ liệu:
1 thanh 0001_initial 2019-11-13 17: 32: 39.701784
Khi chúng tôi chạy:
python manage.py runserver
cảnh báo sau đây sẽ được nêu ra:
Bạn có 1 di chuyển chưa được áp dụng. Dự án của bạn có thể không hoạt động đúng cho đến khi bạn áp dụng chuyển đổi cho (các) ứng dụng: thanh.
Chạy 'python Manage.py di chuyển' để áp dụng chúng.
Tất cả mọi thứ dường như làm việc tốt mặc dù. Tuy nhiên, nó không thỏa mãn khi có cảnh báo này.
Cách thích hợp sẽ là chạy tất cả các di chuyển cho mỗi cơ sở dữ liệu như được đề xuất trong câu trả lời này .
Nó sẽ trông như thế này:
python manage.py migrate --database=default
python manage.py migrate --database=remote
và sau khi tạo các chuyển đổi cho bar:
python manage.py migrate bar --database=default
python manage.py migrate bar --database=remote
Bộ định tuyến sẽ quan tâm rằng bảng bar_bazchỉ được tạo trong remotecơ sở dữ liệu, nhưng Django sẽ đánh dấu các lần di chuyển như được áp dụng trong cả hai cơ sở dữ liệu. Ngoài ra các bảng cho auth, admin, sessions, vv sẽ được tạo ra duy nhất trong defaultcơ sở dữ liệu, theo quy định tại routers.py. Bảng django_migrationstrong remotecơ sở dữ liệu cũng sẽ có các bản ghi cho các lần di chuyển này.
Đó là một bài đọc dài, nhưng tôi hy vọng nó làm sáng tỏ điều này, theo ý kiến của tôi, không giải thích cặn kẽ vấn đề trong tài liệu chính thức .