Birden Fazla Veri Tabanı Kullanımı
Birden Fazla Veri Tabanı Kullanımı¶
Birden fazla veri tabanı kullanmak için öncelikle projemizin settings.py dosyasına eklemeler yaparak bu veri tabanlarını tanımlamamız gerekiyor örnek olarak aşağıda bir postgresql ve mysql veri tabanları için settings.py ayarı var birden fazla ve aynı olmayan tür olmayan veri tabanlarınıda kullanabiliyoruz.
DATABASES = {
'default': { # varsayılan olarak ayarladığımız ver tabanımız
'NAME': 'app_data', # veri tabanı ismi
'ENGINE': 'django.db.backends.postgresql', # veri tabanı türü
'USER': 'postgres_user', # kullanıcı
'PASSWORD': 's3krit' # ve şifre bunları yazma amacımızı bende bilmiyorum bilen varsa yoruma yazarsa düzeltme eklerim
},
'users': { #sadece kullanıcları kayıt etmek için açmış olduğumuz ( erişme adı users olan user_data isimli )veri tabanı
'NAME': 'user_data',
'ENGINE': 'django.db.backends.mysql',
'USER': 'mysql_user',
'PASSWORD': 'priv4te'
}
}
Tabiki varsayılan bir veri tabanı kullanmak istemiyorsanız kullanmaya bilirsiniz bunun için default kısmını boş bırakmalısınız şu şekilde ;
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'
}
}
Veritabanlarınızı Senkronize Etme¶
Veri tabanı senkronizasyonu komutu bir seferde bir veritabanı üzerinde çalışır. Varsayılan olarak, varsayılan veritabanı üzerinde çalışır, ancak —database seçeneğini sağlayarak farklı bir veritabanını senkronize etmesini söyleyebilirsiniz. Dolayısıyla, yukarıdaki ilk örnekteki tüm veritabanlarına tüm modelleri senkronize etmek için aşağıdakileri gibi yapmanız gerekir.
$ ./manage.py migrate # varsayılan olarak ayarladığınız veri tabanı senkronize olur
$ ./manage.py migrate --database=users # erişme ismi users olan veri tabanı senkronize olur
Bu da bir diğer örnek varsayılanı boş yaptığımız için
$ ./manage.py migrate --database=users
$ ./manage.py migrate --database=customers
Diğer Yönetim Komutlarını Kullanma¶
Veritabanı ile etkileşim kuran diğer çoğu django-admin komutu, taşıdıkça çalışır; yalnızca bir defada yalnızca bir veritabanında çalışır; kullanılan veritabanı denetiminde —database kullanılır.
Bu kuralın bir istisnası makemigrations komutudur. Yeni geçişler oluşturmadan önce varolan taşıma dosyalarıyla \(bunları düzenlemeyle oluşabilecek\) sorunları yakalamak için veritabanlarındaki geçiş geçmişini doğrular. Varsayılan olarak, yalnızca varsayılan veritabanını denetler, ancak varsa yönlendiricilerin allow_migrate () yöntemini inceler.
Otomatik Veritabanı Yönlendirme \( Routing \)¶
Birden çok veritabanını kullanmanın en kolay yolu, bir veritabanı yönlendirme şeması oluşturmaktır. Varsayılan yönlendirme şeması, nesnelerin orijinal veritabanına ‘yapışkan’ kalmasını sağlar \(yani, foo veritabanından alınan bir nesne aynı veritabanına kaydedilir\). Varsayılan yönlendirme şeması, bir veritabanı belirtilmemişse, tüm sorgular varsayılan veritabanına geri dönmesini sağlar.
Varsayılan yönlendirme şemasını etkinleştirmek için herhangi bir şey yapmak zorunda değilsiniz - her Django projesinde ‘kutunun dışında’ sağlanmaktadır. Bununla birlikte, daha ilginç veritabanı tahsis davranışlarını uygulamak isterseniz, kendi veritabanı yönlendiricilerinizi tanımlayabilir ve kurabilirsiniz.
Veritabanı Yönlendiricileri¶
Bir veri tabanı Yönlendirici, dört method sağlayan bir sınıftır: Buralar teknik bilgi çok takılmayın daha aşağıda kodlarla örneklenecektir daha iyi anlarsınız
db_for_read \(model, \*\*hints\)¶
okuma işlemleri için
Model tipli nesneleri okuma işlemleri için kullanılması gereken veritabanını bildirin
Bir veritabanı işlemi, bir veritabanını seçmede yardımcı olabilecek herhangi bir ilave bilgi sağlayabilirse, hints sözlüğünde sağlanacaktır. Geçerli hints ile ilgili ayrıntılar aşağıda verilmiştir.
Herhangi bir öneri yoksa None döndürür.
db_for_write \(model, \*\*hints\)¶
yazma işlemleri için
Model modelindeki nesnelerin yazımında kullanılması gereken veritabanını bildirir3
Bir veritabanı işlemi, bir veritabanını seçmede yardımcı olabilecek herhangi bir ilave bilgi sağlayabilirse, hints sözlüğünde sağlanacaktır. Geçerli ipuçları ile ilgili ayrıntılar aşağıda verilmiştir.
Herhangi bir öneri yoksa None döndürür.
allow_relation \(obj1, obj2, \*\*hints\)¶
veri tabanındaki nesne arasındaki ilişkiler için
Obj1 ve obj2 arasındaki bir ilişkiye izin verilirse True
değerini döndürür,
İlişki önlenmeli ise False
döndürür, None
ise seçeneği yoktur.
Bu yanlızca bir doğrulama işlemi dir, foreign key ve many to many İki nesne arasında bir ilişki olup olmadığının belirlenmesi sağlar.
allow_migrate\(db, app_label, model_name=None, \*\*hints\)¶
\( migrate \) taşıma işlemleri için
Geçiş işleminin, takma ad \( db \) veritabanı ile veritabanında çalışmasına izin verilip verilmeyeceğini belirler. İşlemi çalıştırması gerekiyorsa True
, aksi halde çalışmaması durumunda False
veya yönlendiricinin \( router \) fikri yoksa None
döndürür.
app_label konumsal argümanı, taşınan \( migrated yapılan \) uygulamanın etiketidir.
modelname çoğu taşıma \( migrations \) işlemi tarafından taşınan modelin model._meta.model_name \(model_name 'in küçük harfli versiyonu\) değerine ayarlanır .
İpuçlarını \( hints \) kullanmadığı sürece, RunPython ve RunSQL işlemleri için None
değerini döndürür.
ipuçları \( hints \) yönlendiriciye ek bilgi iletmek için bazı işlemler tarafından kullanılır.
Model_name ayarlı olduğunda, ipuçları normalde ‘model’ anahtarının altındaki model sınıfını içerir. Tarihsel bir model olabileceğini ve bu nedenle herhangi bir özel nitelik, yöntem veya yöneticinin olmadığını unutmayın. Sadece _meta’ya güvenmelisin.
Bu yöntem, belirli bir veritabanında bir modelin kullanılabilirliğini belirlemek için de kullanılabilir.
makemigrations
her zaman model değişiklikleri için geçişler oluşturur, ancak allow_migrate()
yanlış döndürürse, db için geçiş işlemi gerçekleştirilirken model_name için yapılan tüm taşıma işlemleri sessizce atlanır. Zaten geçiş götüren modeller için allow_migrate()
işlevinin değiştirilmesi, yabancı anahtarların, ek tabloların veya eksik tabloların kopmasına neden olabilir. Makemigrations, geçiş geçmişini doğruladığında hiçbir uygulamanın geçiş yapmasına izin verilmeyen veritabanlarını atlar.
Yönelticinin tüm bu yöntemleri sunması gerekmez - bir veya daha fazlasını atlayabilir. Yöntemlerden biri atlanırsa, Django ilgili denetimi yaparken bu yönlendirici atlayacaktır.
Hints \( İpuçlar\)¶
Veritabanı yönlendiricisi tarafından alınan ipuçları, hangi veritabanının belirli bir isteği alması gerektiğine karar vermek için kullanılabilir.
Şu anda, sağlanacak tek ipucu, yürütülmekte olan okuma veya yazma işlemi ile ilişkili bir nesne örneği. Bu kaydedilen örnek olabilir veya çoktan çoklu ilişkide eklenen bir örnek olabilir. Bazı durumlarda hiçbir örnek ipucu verilmez. Yöneltici bir örnek ipucu varlığını denetler ve bu ipucunun yönlendirme davranışını değiştirmek için kullanılıp kullanılmayacağını belirler.
Yönlendiricileri Kullanma¶
Veritabanı yönlendiricileri, DATABASE_ROUTERS
ayarı kullanılarak yüklenir settings.py de ayarlanması gerekir. Bu ayar, her biri ana yönlendirici (django.db.router)
tarafından kullanılmak üzere bir yönlendirici belirterek sınıf adlarının bir listesini tanımlar.
Ana yönlendirici, veritabanı kullanımını tahsis etmek için Django’nun veritabanı işlemleri tarafından kullanılır. Bir sorgu hangi veritabanını kullanacağını bilmeye ihtiyaç duyduğunda, bir model ve bir ipucu \(varsa\) sağlayarak ana yönlendirici çağırır. Django, daha sonra bir veritabanı önerisi bulunana kadar her yönlendiriciyi dener. Hiçbir öneri bulunamazsa, ipucu örneğinin geçerli _state.db dosyasını dener. Bir ipucu örneği sağlanmazsa veya örnek şu anda veritabanı durumuna sahip değilse, ana yönlendirici varsayılan veritabanını tahsis edecektir.
Settings.py¶
DATABASE_ROUTERS = [] # şeklinde olmalı
Örnek verelim ve bu örneğin veri tabanı ayarları nasıl olacak bakalım;
DATABASES = {
'default': {}, # varsayılan bir veri tabanı kullanmıyoruz bu yüzden boş
'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',
},
}
Şimdi rota ayarlamamız gerekiyor. İlk önce, auth uygulaması için sorgular gönderilmesini bilen bir router’ı auth_db için ayarlayacağız.
class AuthRouter(object):
# AuthRouter isminde sadece auth_db kullanma ismini verdiğimiz veri tabanı rauterini ayarlayacağız
# yani sadece auth_db isimli veri tabanı içindir bu
"""
Tüm veritabanı işlemlerini kontrol eden yönlendirici
kimlik doğrulama uygulamasının modeldir.
"""
def db_for_read(self, model, **hints):
"""
auth_db'ye giden yetkili modelleri (auth models) Okumaya çalışır.
"""
if model._meta.app_label == 'auth':
return 'auth_db'
return None
def db_for_write(self, model, **hints):
"""
Attempts to write auth models go to auth_db.
"""
if model._meta.app_label == 'auth':
return 'auth_db'
return None
def allow_relation(self, obj1, obj2, **hints):
"""
Yetkilendirme uygulamasındaki bir model dahil edilirse ilişkilere izin ver.
iki nesne de auth a ait ise ilişkiye izin veriyor
"""
if obj1._meta.app_label == 'auth' or \
obj2._meta.app_label == 'auth':
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
Auth uygulamasının yalnızca 'auth_db' veritabanında göründüğünden emin olun.
"""
if app_label == 'auth':
return db == 'auth_db'
return None
Ayrıca diğer tüm uygulamaları birincil / çoğaltma yapılandırmasına gönderen bir yönlendirici istiyoruz ve aşağıdakileri okumak için rasgele bir kopya seçiyor:
import random
class PrimaryReplicaRouter(object):
def db_for_read(self, model, **hints):
"""
Okumalar, rasgele seçilen kopyaya gidiyor.
"""
return random.choice(['replica1', 'replica2'])
def db_for_write(self, model, **hints):
"""
Yazmak için daima primary'w gidiyor.
"""
return 'primary'
def allow_relation(self, obj1, obj2, **hints):
"""
Her iki nesne primary/replica havuzunda bulunuyorsa,
nesneler arasındaki ilişkilere izin verilir.
"""
db_list = ('primary', 'replica1', 'replica2')
if obj1._state.db in db_list and obj2._state.db in db_list:
return True
return None
def allow_migrate(self, db, app_label, model_name=None, **hints):
"""
Tüm auth olmayan modeller bu havuza girer.
"""
return True
Diğer veri tabanlarını içinde rauter tanımladığımıza göre son olarak, ayarlar dosyasında aşağıdakileri ekliyebiliriz \(yönlendiricilerin tanımlandığı modüllere / noktalara gerçek Python yolunu değiştirerek\):
DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.PrimaryReplicaRouter']
sınıf isimlerini veriyoruz burası önem li çünkü yanlış girerseniz django sınıf yolunu bulamaz \(yönlendiricilerin tanımlandığı modüllere / noktalara gerçek Python yolunu değiştirerek\)yazın
Veritabanı El İle Seçme¶
Django, kodunuzda veritabanı kullanımı üzerinde tam kontrol sahibi olmanızı sağlayan bir API de sağlar. Elle belirlenen bir veritabanı tahsisi, bir yönlendirici tarafından ayrılan bir veritabanına göre öncelik taşır.
Bir QuerySet İçin Bir Veritabanı El İle Seçme¶
Bunun için using()
fonksiyonunu kullancağız, örnek olarak
>>> # bu kod varsayılan olarak ayarladığınız veri tabanından nesne çeker
>>> Author.objects.all()
>>> # ve bu
>>> Author.objects.using('default').all()
>>> # ama bu other olarak ayarlanan veri tabanından veri çeker
>>> Author.objects.using('other').all()
veri tabanlarına yeni veriyi kayıt etmek içinde using() kullanılır örnek
my_object.save(using='legacy_users')
# bu kod aldığı veriyi "legacy_users" adlı veri tabanına kayıt eder
silme işlemi için yine aynı
u = User.objects.using('legacy_users').get(username='fred')
u.delete() # `legacy_users` veri tabanındaki veriyi siler
Birden Fazla Veri Tabanı İçin Admin Arayüzü Ayarı¶
class MultiDBModelAdmin(admin.ModelAdmin):
# Alternatif veritabanı adı için kullanışlı bir sabit.
using = 'other' # kullanılacak olan veri tabanı ismi
def save_model(self, request, obj, form, change):
# django ya kayıt yapılacak nesne veri tabanının 'other' olduğunu söyler
obj.save(using=self.using)
def delete_model(self, request, obj):
#djangoya silme işlemi için 'other' veri tabanı olduğunu söyler
obj.delete(using=self.using)
def get_queryset(self, request):
#Django'ya 'diğer' veritabanındaki nesneleri aramasını söyler.
return super(MultiDBModelAdmin, self).get_queryset(request).using(self.using)
def formfield_for_foreignkey(self, db_field, request, **kwargs):
# Django'ya bir Sorgu kullanarak ForeignKey widget'lerini yerleştirmesini söyler
# 'other' veri tabanında tabikide
return super(MultiDBModelAdmin, self).formfield_for_foreignkey(db_field, request, using=self.using, **kwargs)
def formfield_for_manytomany(self, db_field, request, **kwargs):
#Django'ya, 'other' veritabanında bir sorgu kullanarak ManyToMany
# widget'lerini doldurmasını söyle.
return super(MultiDBModelAdmin, self).formfield_for_manytomany(db_field, request, using=self.using, **kwargs)
class MultiDBTabularInline(admin.TabularInline):
using = 'other'
def get_queryset(self, request):
# Django'ya 'other' veritabanındaki satıriçi nesneleri aramasını söyle.
return super(MultiDBTabularInline, self).get_queryset(request).using(self.using)
def formfield_for_foreignkey(self, db_field, request, **kwargs):
# Django'ya, 'other' veritabanında bir sorgu kullanarak
# ForeignKey widget'lerini yerleştirmesini söyle.
return super(MultiDBTabularInline, self).formfield_for_foreignkey(db_field, request, using=self.using, **kwargs)
def formfield_for_manytomany(self, db_field, request, **kwargs):
# Django'ya, "other" veritabanında bir sorgu kullanarak
# ManyToMany widget'lerini doldurmasını söyle.
return super(MultiDBTabularInline, self).formfield_for_manytomany(db_field, request, using=self.using, **kwargs)
yine admin py de yaptığımız sınıfları register ile yolluyoruz
from django.contrib import admin
# Belirli modellerle kullanmak için multi-db admin nesnelerini özelleştirme
class BookInline(MultiDBTabularInline):
model = Book
class PublisherAdmin(MultiDBModelAdmin):
inlines = [BookInline]
admin.site.register(Author, MultiDBModelAdmin)
admin.site.register(Publisher, PublisherAdmin)
othersite = admin.AdminSite('othersite')
othersite.register(Publisher, MultiDBModelAdmin)
Source¶
Created: April 16, 2024