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_migrations
khi 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 foo
và một ứng dụng bar
bên trong dự án. Ứng dụng bar
nà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.py
chú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=default
là 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 bar
và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.py
bê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 bar
vào remote
cơ 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 remote
cơ 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_baz
chỉ được tạo trong remote
cơ 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 default
cơ sở dữ liệu, theo quy định tại routers.py
. Bảng django_migrations
trong remote
cơ 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 .