Birden fazla veri taban kullanm multi db
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
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\):
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)