Black Showman dan Pembunuhan di Kota Tak BernamaPembunuhan bisa terjadi di mana saja, termasuk di sebuah kota kecil, terpencil, dan nyaris terlupakan di tengah pandemi Covid-19. Seorang mantan guru SMP ditemukan tewas tercekik di halaman rumahnya sendiri. Buy |
Koneksi kedatabase menjadi suatu hal yang wajib untuk setiap aplikasi yang terhubung dengan basis data, sebuah framework yang menerapkan konsep ORM seharusnya mampu menangani pekerjaan multi koneksi database. Hal ini penting karena dalam pemrosesan data terkadang bagian data yang kita olah terpisah dengan database utama, beruntungnya django framework cukup mampu melakukan hal ini.
Database dapat memiliki alias apa pun yang Anda pilih. Namun, alias default memiliki arti khusus. Django menggunakan database dengan alias default ketika tidak ada database lain yang dipilih.
perhatikan sample dibawah ini :
DATABASES = {
'default': {
'NAME': 'app_data',
'ENGINE': 'django.db.backends.postgresql',
'USER': 'postgres_user',
'PASSWORD': 's3krit'
},
'users': {
'NAME': 'user_data',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'priv4te'
}
}
Jika konsep database default tidak sesuai dalam konteks proyek Anda, Anda harus berhati-hati untuk selalu menentukan database yang ingin Anda gunakan. Django mensyaratkan bahwa entri database default harus ditentukan, tetapi parameter ini dapat dibiarkan kosong jika tidak akan digunakan. Untuk melakukan ini, Anda harus menyiapkan DATABASE_ROUTERS untuk semua model aplikasi Anda, termasuk yang ada di kontrib dan aplikasi pihak ketiga apa pun yang Anda gunakan, sehingga tidak ada kueri yang dialihkan ke database default.
Perhatikan contoh dibawah ini :
DATABASES = {
'default': {},
'users': {
'NAME': 'user_data',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'superS3cret'
},
'customers': {
'NAME': 'customer_data',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_cust',
'PASSWORD': 'veryPriv@ate'
}
}
./manage.py migrate
./manage.py migrate --database=users
Jika Anda tidak ingin setiap aplikasi disinkronkan ke basis data tertentu, Anda dapat menentukan route basis data yang mengimplementasikan kebijakan yang membatasi ketersediaan model tertentu.
Jika, seperti dalam contoh kedua di atas, Anda membiarkan database default kosong, Anda harus memberikan nama database setiap kali Anda menjalankan migrasi. Mengabaikan nama basis data akan memunculkan kesalahan.
Perhatikan contoh dibawah ini:
./manage.py migrate --database=users
./manage.py migrate --database=customers
db_for_read
(model, **hints)db_for_write
(model, **hints)allow_relation
(obj1, obj2, **hints)allow_migrate
(db, app_label, model_name=None, **hints)DATABASES = {
'default': {},
'auth_db': {
'NAME': 'auth_db',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'swordfish',
},
'primary': {
'NAME': 'primary',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'spam',
},
'replica1': {
'NAME': 'replica1',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'eggs',
},
'replica2': {
'NAME': 'replica2',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'bacon',
},
}
class AuthRouter:
"""
A router to control all database operations on models in the
auth and contenttypes applications.
"""
route_app_labels = {'auth', 'contenttypes'}def db_for_read(self, model, **hints):
"""
Attempts to read auth and contenttypes models go to auth_db.
"""
if model._meta.app_label in self.route_app_labels:
return 'auth_db'
return Nonedef db_for_write(self, model, **hints):
"""
Attempts to write auth and contenttypes models go to auth_db.
"""
if model._meta.app_label in self.route_app_labels:
return 'auth_db'
return Nonedef allow_relation(self, obj1, obj2, **hints):
"""
Allow relations if a model in the auth or contenttypes apps is
involved.
"""
if (
obj1._meta.app_label in self.route_app_labels or
obj2._meta.app_label in self.route_app_labels
):
return True
return Nonedef allow_migrate(self, db, app_label, model_name=None, **hints):
"""
Make sure the auth and contenttypes apps only appear in the
'auth_db' database.
"""
if app_label in self.route_app_labels:
return db == 'auth_db'
return None
import randomclass PrimaryReplicaRouter:
def db_for_read(self, model, **hints):
"""
Reads go to a randomly-chosen replica.
"""
return random.choice(['replica1', 'replica2'])def db_for_write(self, model, **hints):
"""
Writes always go to primary.
"""
return 'primary'def allow_relation(self, obj1, obj2, **hints):
"""
Relations between objects are allowed if both objects are
in the primary/replica pool.
"""
db_list = ('primary', 'replica1', 'replica2')
if obj1._state.db in db_list and obj2._state.db in db_list:
return True
return Nonedef allow_migrate(self, db, app_label, model_name=None, **hints):
"""
All non-auth models end up in this pool.
"""
return True
# This retrieval will be performed on the 'auth_db' database
fred = User.objects.get(username='fred')
fred.first_name = 'Frederick'# This save will also be directed to 'auth_db'
fred.save()These retrieval will be randomly allocated to a replica database
dna = Person.objects.get(name='Douglas Adams')# A new object has no database allocation when created
mh = Book(title='Mostly Harmless')# This assignment will consult the router, and set mh onto
# the same database as the author object
mh.author = dna# This save will force the 'mh' instance onto the primary database...
mh.save()# ... but if we re-retrieve the object, it will come back on a replica
mh = Book.objects.get(title='Mostly Harmless')
DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.PrimaryReplicaRouter']