Berkat komentar pada pertanyaan saya, saya melakukan riset dan menghasilkan temuan berikut.
Menggunakan banyak basis data menghasilkan pembuatan tabel django_migrations
saat migrasi digunakan. Tidak ada pilihan untuk mencatat migrasi hanya dalam satu tabel django_migrations
, seperti komentar dari Kamil Niski menjelaskan. Ini jelas setelah membaca file django/db/migrations/recorder.py
.
Saya akan menggambarkan contoh dengan proyek foo
dan aplikasi bar
di dalam proyek. Aplikasi bar
ini hanya memiliki satu model Baz
.
Kami membuat proyek:
django-admin startproject foo
Sekarang kita memiliki konten ini di dalam direktori proyek utama:
- foo
- manage.py
Saya memiliki kebiasaan untuk mengelompokkan semua aplikasi di dalam direktori proyek:
mkdir foo/bar
python manage.py bar foo/bar
Dalam file tersebut foo/settings.py
kami menyesuaikan pengaturan untuk menggunakan dua database yang berbeda, untuk keperluan contoh ini kami menggunakan 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'),
}
}
Sekarang kami menjalankan migrasi:
python manage.py migrate --database=default
Ini menjalankan semua migrasi, bagian --database=default
itu opsional, karena jika tidak ditentukan Django menggunakan database default.
Operasi yang harus dilakukan:
Terapkan semua migrasi: admin, auth, tipe konten, sesi
Menjalankan migrasi:
Menerapkan tipe konten.0001_initial ... OK
Menerapkan auth,0001_initial ... OK
Menerapkan admin.0001_initial ... OK
Menerapkan admin.0002_logentry_remove_auto_add ... OK
Menerapkan admin.0003_logentry_add_action_flag_choices ... OK
Menerapkan contenttypes.0002_remove_content_type_name ... OK
Menerapkan auth.0002_alter_permission_name_max_length ... OK
Menerapkan auth,0003_alter_user_email_max_length ... OK
Menerapkan auth,0004_alter_user_username_opts ... OK
Menerapkan auth,0005_alter_user_last_login_null ... OK
Menerapkan auth,0006_require_contenttypes_0002 ... OK
Menerapkan auth.0007_alter_validators_add_error_messages ... OK
Menerapkan auth,0008_alter_user_username_max_length ... OK
Menerapkan auth,0009_alter_user_last_name_max_length ... OK
Menerapkan auth.0010_alter_group_name_max_length ... OK
Menerapkan auth.0011_update_proxy_permissions ... OK
Menerapkan sesi.0001_initial ... OK
Django telah menerapkan semua migrasi ke database default:
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 sesi 0001_initial 2019-11-13 16: 51: 05.063868
Sekarang kami membuat model Baz
:
models.py
:
from django.db import models
class Baz(models.Model):
name = models.CharField(max_length=255, unique=True)
daftarkan aplikasinya bar
ke INSTALLED_APPS
( foo/settings.py
) dan buat themigrations:
python manage.py makemigrations bar
Sebelum kami menjalankan migrasi yang kami buat routers.py
di dalam bar
aplikasi:
kelas BarRouter (objek):
def db_for_read (self, model, ** hints):
jika model._meta.app_label == 'bar':
kembalikan 'jarak jauh'
return Tidak ada
def db_for_write (self, model, ** hints):
jika model._meta.app_label == 'bar':
kembalikan 'jarak jauh'
return Tidak ada
def allow_relation (self, obj1, obj2, ** hints):
return Tidak ada
def allow_migrate (self, db, app_label, model_name = Tidak ada, ** petunjuk):
jika app_label == 'bar':
return db == 'remote'
if db == 'remote':
mengembalikan False
return Tidak ada
dan daftarkan di foo/settings.py
:
DATABASE_ROUTERS = ['foo.bar.routers.BarRouter']
Sekarang pendekatan naif adalah menjalankan migrasi bar
ke dalam remote
database:
python manage.py migrate bar --database=remote
Operasi yang harus dilakukan:
Terapkan semua migrasi: bilah
Menjalankan migrasi:
Menerapkan bar.0001_initial ... OK
Migrasi telah diterapkan ke remote
database:
1 bilah 0001_initial 2019-11-13 17: 32: 39.701784
Ketika kami menjalankan:
python manage.py runserver
peringatan berikut akan dimunculkan:
Anda memiliki 1 migrasi yang tidak diterapkan. Proyek Anda mungkin tidak berfungsi dengan baik sampai Anda menerapkan migrasi untuk aplikasi: bilah.
Jalankan 'python manage.py migrate' untuk menerapkannya.
Segalanya tampak bekerja dengan baik. Namun tidak memuaskan memiliki peringatan ini.
Cara yang tepat adalah menjalankan semua migrasi untuk setiap basis data seperti yang disarankan dalam jawaban ini .
Akan terlihat seperti ini:
python manage.py migrate --database=default
python manage.py migrate --database=remote
dan setelah membuat migrasi untuk bar
:
python manage.py migrate bar --database=default
python manage.py migrate bar --database=remote
Router akan berhati-hati bahwa tabel bar_baz
dibuat hanya dalam remote
database, tetapi Django akan menandai migrasi sebagaimana diterapkan di kedua database. Juga tabel untuk auth
, admin
, sessions
, dll akan dibuat hanya dalam default
basis data, sebagaimana ditentukan dalam routers.py
. Tabel django_migrations
dalam remote
database akan memiliki catatan untuk migrasi ini juga.
Ini adalah bacaan yang panjang, tapi saya harap ini menjelaskan hal ini, menurut pendapat saya, tidak menjelaskan masalah secara menyeluruh dalam dokumentasi resmi .