Django 2.1 - Multiple databases
एकाधिक डेटाबेस

एकाधिक डेटाबेस
यह विषय गाइड कई डेटाबेस के साथ बातचीत के लिए Django के समर्थन का वर्णन करता है। Django के बाकी डॉक्यूमेंट्स में से अधिकांश आप एक ही डेटाबेस के साथ बातचीत कर रहे हैं। यदि आप कई डेटाबेस के साथ बातचीत करना चाहते हैं, तो आपको कुछ अतिरिक्त कदम उठाने होंगे।
यह भी देखें
कई डेटाबेस के साथ परीक्षण के बारे में जानकारी के लिए मल्टी-डेटाबेस समर्थन देखें।
अपने डेटाबेस को परिभाषित करना
Django के साथ एक से अधिक डेटाबेस का उपयोग करने का पहला कदम Django को उन डेटाबेस सर्वरों के बारे में बताना है जिन्हें आप उपयोग कर रहे हैं।
यह
DATABASES
सेटिंग का उपयोग करके किया जाता है।
यह सेटिंग डेटाबेस उपनामों को दर्शाता है, जो कि उस विशिष्ट कनेक्शन के लिए सेटिंग्स के शब्दकोश में, Django में एक विशिष्ट डेटाबेस को संदर्भित करने का एक तरीका है।
आंतरिक शब्दकोशों में सेटिंग्स को पूरी तरह से
DATABASES
प्रलेखन में वर्णित किया गया है।
डेटाबेस में आपके द्वारा चुना गया कोई भी अन्य नाम हो सकता है।
हालांकि, उपनाम
default
का विशेष महत्व है।
Django
default
से उपनाम के साथ डेटाबेस का उपयोग करता है जब कोई अन्य डेटाबेस नहीं चुना गया है।
निम्नलिखित एक उदाहरण
settings.py
दो डेटाबेसों को परिभाषित करने वाला स्निपेट - एक डिफ़ॉल्ट पोस्टग्रैसक्यूएल डेटाबेस और एक माईएसक्यूएल डेटाबेस जिसे
users
कहते
users
:
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' } }
यदि
default
डेटाबेस की अवधारणा आपके प्रोजेक्ट के संदर्भ में कोई मतलब नहीं रखती है, तो आपको उस डेटाबेस को हमेशा निर्दिष्ट करने के लिए सावधान रहने की आवश्यकता है जिसे आप उपयोग करना चाहते हैं।
Django के लिए आवश्यक है कि एक
default
डेटाबेस प्रविष्टि को परिभाषित किया जाए, लेकिन इसका उपयोग नहीं किया जाएगा तो पैरामीटर शब्दकोश को खाली छोड़ दिया जा सकता है।
ऐसा करने के लिए, आपको अपने ऐप्स के सभी मॉडलों के लिए
DATABASE_ROUTERS
सेट करना होगा, जिनमें आपके द्वारा उपयोग किए जा रहे किसी भी कंट्रास्ट और तृतीय-पक्ष ऐप में शामिल हैं, ताकि कोई भी डिफॉल्ट डेटाबेस में कोई प्रश्न न आए।
निम्नलिखित एक उदाहरण
settings.py
दो गैर-डिफ़ॉल्ट डेटाबेस को परिभाषित करने वाला स्निपेट,
default
प्रविष्टि जानबूझकर खाली छोड़ दिया गया है:
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': '[email protected]' } }
यदि आप किसी डेटाबेस को अपने
DATABASES
सेटिंग में परिभाषित नहीं करने का प्रयास करते हैं, तो Django एक
django.db.utils.ConnectionDoesNotExist
अपवाद
django.db.utils.ConnectionDoesNotExist
।
अपने डेटाबेस को सिंक्रनाइज़ करना
migrate
प्रबंधन कमांड एक समय में एक डेटाबेस पर काम करता है।
डिफ़ॉल्ट रूप से, यह
default
डेटाबेस पर काम करता है, लेकिन
--database
विकल्प प्रदान करके, आप इसे किसी भिन्न डेटाबेस को सिंक्रनाइज़ करने के लिए कह सकते हैं।
इसलिए, ऊपर दिए गए पहले उदाहरण में सभी डेटाबेस पर सभी मॉडलों को सिंक्रनाइज़ करने के लिए, आपको कॉल करना होगा:
$ ./manage.py migrate $ ./manage.py migrate --database=users
यदि आप नहीं चाहते कि प्रत्येक एप्लिकेशन किसी विशेष डेटाबेस पर सिंक्रनाइज़ हो, तो आप एक डेटाबेस राउटर को परिभाषित कर सकते हैं जो किसी विशेष मॉडल की उपलब्धता को बाधित करने वाली नीति को लागू करता है।
यदि, ऊपर दिए गए दूसरे उदाहरण के अनुसार, आपने
default
डेटाबेस को खाली छोड़ दिया है, तो आपको
migrate
चलाने के
migrate
हर बार एक डेटाबेस नाम प्रदान करना होगा।
डेटाबेस नाम को छोड़ते समय एक त्रुटि होगी।
दूसरे उदाहरण के लिए:
$ ./manage.py migrate --database=users $ ./manage.py migrate --database=customers
अन्य प्रबंधन आदेशों का उपयोग करना
अधिकांश अन्य
django-admin
कमांड्स जो डेटाबेस के साथ इंटरैक्ट करते हैं, उसी तरह से काम करते हैं जैसे कि वे
migrate
- वे केवल एक समय में एक डेटाबेस पर काम करते हैं,
--database
का उपयोग
--database
गए डेटाबेस को नियंत्रित करने के लिए करते हैं।
इस नियम का अपवाद
makemigrations
कमांड है।
यह नए माइग्रेशन बनाने से पहले मौजूदा माइग्रेशन फ़ाइलों (जो उन्हें संपादित करने के कारण हो सकता है) के साथ समस्याओं को पकड़ने के लिए डेटाबेस में माइग्रेशन इतिहास को मान्य करता है।
डिफ़ॉल्ट रूप से, यह केवल
default
डेटाबेस की जांच करता है, लेकिन यह किसी भी स्थापित होने पर
राउटर
के
allow_migrate()
विधि को
allow_migrate()
है।
स्वचालित डेटाबेस रूटिंग
कई डेटाबेस का उपयोग करने का सबसे आसान तरीका एक डेटाबेस रूटिंग योजना स्थापित करना है।
डिफ़ॉल्ट रूटिंग योजना यह सुनिश्चित करती है कि वस्तुएं अपने मूल डेटाबेस से 'चिपकी रहें' (अर्थात,
foo
डेटाबेस से प्राप्त वस्तु को उसी डेटाबेस में सहेजा जाएगा)।
डिफ़ॉल्ट रूटिंग योजना यह सुनिश्चित करती है कि यदि कोई डेटाबेस निर्दिष्ट नहीं है, तो सभी क्वेरीज़
default
डेटाबेस पर वापस आती हैं।
आपको डिफ़ॉल्ट रूटिंग योजना को सक्रिय करने के लिए कुछ भी करने की ज़रूरत नहीं है - यह हर Django परियोजना पर 'आउट ऑफ द बॉक्स' प्रदान की जाती है। हालांकि, यदि आप अधिक दिलचस्प डेटाबेस आवंटन व्यवहारों को लागू करना चाहते हैं, तो आप अपने स्वयं के डेटाबेस राउटर्स को परिभाषित और स्थापित कर सकते हैं।
डेटाबेस राउटर
डेटाबेस राउटर एक ऐसा वर्ग है जो अधिकतम चार तरीके प्रदान करता है:
-
db_for_read(model, **hints)
-
उस डेटाबेस का सुझाव दें जिसका उपयोग टाइप
model
की वस्तुओं के पढ़ने के लिए किया जाना चाहिए।यदि कोई डेटाबेस ऑपरेशन कोई अतिरिक्त जानकारी प्रदान करने में सक्षम है जो डेटाबेस का चयन करने में सहायता कर सकता है, तो यह
hints
शब्दकोश में प्रदान किया जाएगा। मान्य संकेत पर विवरण below ।यदि कोई सुझाव
None
तोNone
लौटाता है।
-
db_for_write(model, **hints)
-
उस डेटाबेस का सुझाव दें जिसका उपयोग टाइप मॉडल की वस्तुओं के लेखन के लिए किया जाना चाहिए।
यदि कोई डेटाबेस ऑपरेशन कोई अतिरिक्त जानकारी प्रदान करने में सक्षम है जो डेटाबेस का चयन करने में सहायता कर सकता है, तो यह
hints
शब्दकोश में प्रदान किया जाएगा। मान्य संकेत पर विवरण below ।यदि कोई सुझाव
None
तोNone
लौटाता है।
-
allow_relation(obj1, obj2, **hints)
-
True
लौटें अगरobj1
औरobj2
बीच एक संबंध की अनुमति दी जानी चाहिए, तोFalse
यदि संबंध को रोका जाना चाहिए, याNone
अगर राउटर की कोई राय नहीं है। यह विशुद्ध रूप से एक सत्यापन ऑपरेशन है, जिसका उपयोग विदेशी कुंजी और कई ऑपरेशनों द्वारा यह निर्धारित करने के लिए किया जाता है कि दो वस्तुओं के बीच एक संबंध की अनुमति दी जानी चाहिए।यदि किसी राउटर की एक राय नहीं है (यानी सभी राउटर
None
लौटाते हैं), केवल उसी डेटाबेस के भीतर संबंधों की अनुमति है।
-
allow_migrate(db, app_label, model_name=None, **hints)
-
यह निर्धारित करें कि क्या माइग्रेशन ऑपरेशन को अलियास
db
साथ डेटाबेस पर चलने की अनुमति है। यदि ऑपरेशन चलाना चाहिए तोTrue
लौटें, यदि यह नहीं चलना चाहिए, तोFalse
, या यदि राउटर की कोई रायNone
तो कोई भी नहीं।app_label
स्थिति तर्क एप्लिकेशन के माइग्रेट होने का लेबल है।model_name
अधिकांश माइग्रेशन परिचालनों द्वारा मॉडल के मान के लिए सेट किया जाता है। मॉडल__name__
(मॉडल का__name__
संस्करण__name__
) माइग्रेट किया जा रहा है। जब तक वे संकेत का उपयोग करके इसे प्रदान नहीं करते तब तक इसका मूल्यRunPython
औरRunSQL
संचालन के लिए नहीं है।राउटर के लिए अतिरिक्त जानकारी को संप्रेषित करने के लिए कुछ परिचालन द्वारा
hints
का उपयोग किया जाता है।जब
model_name
सेट किया जाता है, तोhints
सामान्य रूप से कुंजी'model'
तहत मॉडल वर्ग में होते हैं। ध्यान दें कि यह एक ऐतिहासिक मॉडल हो सकता है, और इस प्रकार कोई भी कस्टम विशेषताएँ, विधियाँ, या प्रबंधक नहीं हैं। आपको केवल_meta
पर निर्भर रहना चाहिए।इस पद्धति का उपयोग किसी दिए गए डेटाबेस पर मॉडल की उपलब्धता को निर्धारित करने के लिए भी किया जा सकता है।
makemigrations
हमेशा मॉडल परिवर्तनों के लिए माइग्रेशन बनाता है, लेकिन अगरallow_migrate()
False
रिटर्न देता है, तोdb
परmigrate
चलाने परmodel_name
लिए कोई भी माइग्रेशन ऑपरेशन चुपचाप छोड़ दिया जाएगा। पहले से ही माइग्रेशन वाले मॉडल के लिएallow_migrate()
के व्यवहार को बदलने के परिणामस्वरूप टूटी हुई विदेशी कुंजियाँ, अतिरिक्त टेबल या लापता टेबल हो सकते हैं। जबmakemigrations
माइग्रेशन इतिहास की पुष्टि करता है, तो यह उन डेटाबेसों को छोड़ देता है जहां किसी भी ऐप को माइग्रेट करने की अनुमति नहीं है।
एक राउटर को इन सभी तरीकों को प्रदान करने की आवश्यकता नहीं है - यह उनमें से एक या अधिक को छोड़ सकता है। यदि विधियों में से एक को छोड़ दिया जाता है, तो प्रासंगिक जांच करते समय Django उस राउटर को छोड़ देगा।
संकेत
डेटाबेस राउटर द्वारा प्राप्त संकेत का उपयोग यह तय करने के लिए किया जा सकता है कि किस डेटाबेस को दिए गए अनुरोध को प्राप्त करना चाहिए।
वर्तमान में, एकमात्र संकेत जो प्रदान किया जाएगा,
instance
, एक वस्तु उदाहरण है जो पढ़ने या लिखने के संचालन से संबंधित है जो चल रहा है।
यह वह उदाहरण हो सकता है जिसे सहेजा जा रहा है, या यह एक उदाहरण हो सकता है जिसे कई-से-कई संबंधों में जोड़ा जा रहा है।
कुछ मामलों में, कोई उदाहरण संकेत उपलब्ध नहीं कराया जाएगा।
राउटर एक संकेत संकेत के अस्तित्व की जांच करता है, और यह निर्धारित करता है कि रूटिंग व्यवहार को बदलने के लिए उस संकेत का उपयोग किया जाना चाहिए।
राउटर का उपयोग करना
डेटाबेस राउटर
DATABASE_ROUTERS
सेटिंग का उपयोग करके इंस्टॉल किए जाते हैं।
यह सेटिंग क्लास नामों की एक सूची को परिभाषित करती है, प्रत्येक राउटर को मास्टर राउटर (
django.db.router
) द्वारा निर्दिष्ट किया जाना चाहिए।
मास्टर राउटर का उपयोग Django के डेटाबेस संचालन द्वारा डेटाबेस उपयोग को आवंटित करने के लिए किया जाता है।
जब भी किसी क्वेरी को जानना होता है कि किस डेटाबेस का उपयोग करना है, तो यह मास्टर राउटर को कॉल करता है, एक मॉडल और एक संकेत प्रदान करता है (यदि उपलब्ध हो)।
Django तब प्रत्येक राउटर को बदले में तब तक आज़माता है जब तक कि एक डेटाबेस सुझाव नहीं मिलता है।
यदि कोई सुझाव नहीं मिल सकता है, तो यह संकेत के वर्तमान
_state.db
को
_state.db
करता है।
यदि एक संकेत उदाहरण प्रदान नहीं किया गया था, या उदाहरण में वर्तमान में डेटाबेस स्थिति नहीं है, तो मास्टर राउटर
default
डेटाबेस को आवंटित करेगा।
एक उदाहरण
केवल उदाहरण के लिए!
यह उदाहरण राउटर के बुनियादी ढांचे के डेटाबेस के उपयोग को बदलने के लिए कैसे उपयोग किया जा सकता है, के प्रदर्शन के रूप में अभिप्रेत है। यह जानबूझकर कुछ जटिल मुद्दों की अनदेखी करता है कि कैसे राउटर्स का उपयोग किया जाता है।
यह उदाहरण काम नहीं करेगा यदि किसी भी
myapp
में किसी मॉडल में
other
डेटाबेस के बाहर के मॉडल से संबंध हैं।
क्रॉस-डेटाबेस रिश्ते
रेफरल अखंडता समस्याओं को पेश करते हैं जो कि Django वर्तमान में नहीं संभाल सकता है।
वर्णित प्राथमिक / प्रतिकृति (कुछ डेटाबेस द्वारा मास्टर / दास के रूप में संदर्भित) विन्यास भी त्रुटिपूर्ण है - यह प्रतिकृति अंतराल से निपटने के लिए कोई समाधान प्रदान नहीं करता है (यानी, प्रश्न के प्रचार के लिए लिखे गए समय के कारण शुरू की गई क्वेरी असंगतताएं। प्रतिकृतियां)। यह डेटाबेस उपयोग रणनीति के साथ लेनदेन की बातचीत पर भी विचार नहीं करता है।
तो - व्यवहार में इसका क्या मतलब है? आइए एक और नमूना विन्यास पर विचार करें। यह एक कई डेटाबेस होगा: एक के लिए एक अनुप्रयोग, और दो अन्य सभी एप्लिकेशन के साथ एक प्राथमिक / प्रतिकृति सेटअप का उपयोग करते हुए। यहां इन डेटाबेस को निर्दिष्ट करने वाली सेटिंग दी गई है:
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', }, }
अब हमें रूटिंग को संभालने की आवश्यकता होगी।
सबसे पहले हम एक राउटर चाहते हैं जो
auth_db
लिए
auth_db
ऐप के लिए प्रश्न भेजना जानता है:
class AuthRouter: """ A router to control all database operations on models in the auth application. """ def db_for_read(self, model, **hints): """ Attempts to read auth models go to auth_db. """ 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): """ Allow relations if a model in the auth app is involved. """ 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): """ Make sure the auth app only appears in the 'auth_db' database. """ if app_label == 'auth': return db == 'auth_db' return None
और हम ऐसा राउटर भी चाहते हैं जो अन्य सभी ऐप्स को प्राइमरी / रेप्लिका कॉन्फ़िगरेशन में भेजता है, और बेतरतीब ढंग से पढ़ने के लिए एक प्रतिकृति चुनता है:
import random class 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 None def allow_migrate(self, db, app_label, model_name=None, **hints): """ All non-auth models end up in this pool. """ return True
अंत में, सेटिंग्स फ़ाइल में, हम निम्नलिखित जोड़ते हैं (पथ का प्रतिस्थापन
path.to.
रहे हैं। वास्तविक पायथन पथ के साथ मॉड्यूल (रों) जहां राउटर्स को परिभाषित किया गया है):
DATABASE_ROUTERS = ['path.to.AuthRouter', 'path.to.PrimaryReplicaRouter']
जिस क्रम में राउटर को संसाधित किया जाता है वह महत्वपूर्ण है।
राउटर्स को
DATABASE_ROUTERS
सेटिंग में सूचीबद्ध क्रम में क्वेर किया जाएगा।
इस उदाहरण में,
AuthRouter
को
AuthRouter
से पहले संसाधित किया
PrimaryReplicaRouter
, और परिणामस्वरूप, किसी भी अन्य निर्णय के पहले ही मॉडल के विषय में निर्णय संसाधित किए जाते हैं।
यदि
DATABASE_ROUTERS
सेटिंग ने दूसरे क्रम में दो राउटर सूचीबद्ध किए हैं, तो
PrimaryReplicaRouter.allow_migrate()
को पहले संसाधित किया जाएगा।
PrimaryReplicaRouter कार्यान्वयन की पकड़-सभी प्रकृति का मतलब होगा कि सभी मॉडल सभी डेटाबेस पर उपलब्ध होंगे।
इस सेटअप के साथ, कुछ Django कोड चलाने की सुविधा देता है:
>>> # 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')
इस उदाहरण ने राउटर को दूसरे ऐप के मॉडल के साथ इंटरैक्शन को संभालने के लिए और अन्य राउटरों को अन्य सभी ऐप के साथ बातचीत को संभालने के लिए परिभाषित किया है।
यदि आपने अपना
default
डेटाबेस खाली छोड़ दिया है और सभी ऐप्स को अन्यथा निर्दिष्ट नहीं करने के लिए पकड़ने के लिए सभी डेटाबेस राउटर को परिभाषित नहीं करना चाहते हैं, तो आपके राउटर को माइग्रेट करने से पहले
INSTALLED_APPS
में सभी ऐप्स के नाम को संभालना होगा।
उन कॉन्ट्रिब ऐप्स
के बारे में जानकारी के लिए
कंट्राब ऐप का व्यवहार
देखें जो एक डेटाबेस में एक साथ होने चाहिए।
मैन्युअल रूप से एक डेटाबेस का चयन
Django भी एक एपीआई प्रदान करता है जो आपको अपने कोड में डेटाबेस उपयोग पर पूर्ण नियंत्रण बनाए रखने की अनुमति देता है। एक मैन्युअल रूप से निर्दिष्ट डेटाबेस आवंटन एक राउटर द्वारा आवंटित डेटाबेस पर प्राथमिकता देगा।
मैन्युअल रूप से
QuerySet
लिए डेटाबेस का चयन
QuerySet
आप
QuerySet
"चेन" के किसी भी बिंदु पर एक
QuerySet
लिए डेटाबेस का चयन कर सकते हैं। निर्दिष्ट डेटाबेस का उपयोग करने वाले किसी अन्य
QuerySet
को प्राप्त करने के लिए
QuerySet
पर बस
using()
कॉल करें।
using()
एकल तर्क लेता है: डेटाबेस का उपनाम जिस पर आप क्वेरी चलाना चाहते हैं।
उदाहरण के लिए:
>>> # This will run on the 'default' database. >>> Author.objects.all() >>> # So will this. >>> Author.objects.using('default').all() >>> # This will run on the 'other' database. >>> Author.objects.using('other').all()
save()
लिए एक डेटाबेस का चयन
save()
किस डेटाबेस को डेटा सहेजा जाना चाहिए यह निर्दिष्ट करने के लिए
Model.save()
using
कीवर्ड का
using
करें।
उदाहरण के लिए, किसी ऑब्जेक्ट को
legacy_users
डेटाबेस में
legacy_users
, आप इसका उपयोग करेंगे:
>>> my_object.save(using='legacy_users')
यदि आप
using
करना निर्दिष्ट नहीं
using
, तो राउटर द्वारा आवंटित डिफ़ॉल्ट डेटाबेस में
save()
विधि बच जाएगी।
किसी ऑब्जेक्ट को एक डेटाबेस से दूसरे में ले जाना
यदि आपने एक डेटाबेस में एक इंस्टेंस को सेव किया है, तो इंस्टेंस को नए डेटाबेस में माइग्रेट करने के तरीके के रूप में
save(using=...)
उपयोग करने के लिए लुभावना हो सकता है।
हालाँकि, यदि आप उचित कदम नहीं उठाते हैं, तो इसके कुछ अप्रत्याशित परिणाम हो सकते हैं।
निम्नलिखित उदाहरण पर विचार करें:
>>> p = Person(name='Fred') >>> p.save(using='first') # (statement 1) >>> p.save(using='second') # (statement 2)
कथन 1 में, एक नया
Person
ऑब्जेक्ट
first
डेटाबेस में सहेजा गया है।
इस समय,
p
पास प्राथमिक कुंजी नहीं है, इसलिए Django SQL
INSERT
स्टेटमेंट जारी करता है।
यह एक प्राथमिक कुंजी बनाता है, और Django उस प्राथमिक कुंजी को
p
असाइन करता है।
जब स्टेटमेंट 2 में सेव होता है,
p
पहले से ही एक प्राथमिक कुंजी है, और Django नए डेटाबेस पर उस प्राथमिक कुंजी का उपयोग करने का प्रयास करेगा।
यदि
second
डेटाबेस में प्राथमिक कुंजी मूल्य उपयोग में नहीं है, तो आपको कोई समस्या नहीं होगी - ऑब्जेक्ट को नए डेटाबेस में कॉपी किया जाएगा।
हालांकि, यदि
p
की प्राथमिक कुंजी पहले से ही
second
डेटाबेस पर उपयोग में है, तो
p
को सहेजे जाने पर
second
डेटाबेस में मौजूदा ऑब्जेक्ट को ओवरराइड किया जाएगा।
आप इससे दो तरह से बच सकते हैं।
सबसे पहले, आप उदाहरण की प्राथमिक कुंजी को साफ़ कर सकते हैं।
यदि किसी ऑब्जेक्ट में कोई प्राथमिक कुंजी नहीं है, तो
second
डेटाबेस पर डेटा के किसी भी नुकसान से बचने के लिए, Django इसे एक नई वस्तु के रूप में मानेगा:
>>> p = Person(name='Fred') >>> p.save(using='first') >>> p.pk = None # Clear the primary key. >>> p.save(using='second') # Write a completely new object.
दूसरा विकल्प यह है कि Django SQL
INSERT
करता है यह सुनिश्चित करने के
save()
को
save()
लिए
force_insert
विकल्प का उपयोग
INSERT
:
>>> p = Person(name='Fred') >>> p.save(using='first') >>> p.save(using='second', force_insert=True)
यह सुनिश्चित करेगा कि
Fred
नाम का व्यक्ति दोनों डेटाबेस पर एक ही प्राथमिक कुंजी रखेगा।
यदि आप
second
डेटाबेस पर सहेजने का प्रयास करते हैं तो प्राथमिक कुंजी पहले से ही उपयोग में है, एक त्रुटि उठाई जाएगी।
से हटाने के लिए डेटाबेस का चयन करना
डिफ़ॉल्ट रूप से, किसी मौजूदा ऑब्जेक्ट को हटाने के लिए कॉल को उसी डेटाबेस पर निष्पादित किया जाएगा जिसका उपयोग पहली जगह में ऑब्जेक्ट को प्राप्त करने के लिए किया गया था:
>>> u = User.objects.using('legacy_users').get(username='fred') >>> u.delete() # will delete from the `legacy_users` database
उस डेटाबेस को निर्दिष्ट करने के लिए जिसमें से एक मॉडल हटा दिया जाएगा,
Model.delete()
विधि के लिए एक कीवर्ड तर्क
using
।
यह तर्क
save()
using
करते
using
कीवर्ड तर्क की तरह काम करता है।
उदाहरण के लिए, यदि आप किसी उपयोगकर्ता को
legacy_users
डेटाबेस से
legacy_users
डेटाबेस में माइग्रेट कर रहे हैं, तो आप इन आदेशों का उपयोग कर सकते हैं:
>>> user_obj.save(using='new_users') >>> user_obj.delete(using='legacy_users')
एकाधिक डेटाबेस वाले प्रबंधकों का उपयोग करना
प्रबंधकों को गैर-डिफ़ॉल्ट डेटाबेस तक पहुँच देने के लिए
db_manager()
पद्धति का उपयोग करें।
उदाहरण के लिए,
User.objects.create_user()
कि आपके पास एक कस्टम प्रबंधक विधि है जो डेटाबेस को छूती है -
User.objects.create_user()
।
क्योंकि
create_user()
एक प्रबंधक विधि है,
QuerySet
विधि नहीं, आप
User.objects.using('new_users').create_user()
नहीं कर सकते हैं
User.objects.using('new_users').create_user()
।
(
create_user()
विधि केवल
User.objects
पर उपलब्ध है, प्रबंधक, प्रबंधक से प्राप्त
QuerySet
ऑब्जेक्ट पर नहीं।) समाधान
db_manager()
का उपयोग
db_manager()
, इस तरह:
User.objects.db_manager('new_users').create_user(...)
db_manager()
आपके द्वारा निर्दिष्ट डेटाबेस के लिए प्रबंधक की एक प्रति लौटाता है।
कई डेटाबेस के साथ
get_queryset()
का उपयोग करना
यदि आप अपने प्रबंधक पर
get_queryset()
को ओवरराइड कर रहे हैं, तो या तो पैरेंट पर विधि (
super()
का उपयोग करके
super()
को कॉल करना सुनिश्चित करें या प्रबंधक पर
_db
विशेषता का उचित हैंडलिंग (डेटाबेस के नाम से युक्त एक स्ट्रिंग) करें उपयोग)।
उदाहरण के लिए, यदि आप
QuerySet
विधि से एक कस्टम
QuerySet
वर्ग वापस करना चाहते हैं, तो आप ऐसा कर सकते हैं:
class MyManager(models.Manager): def get_queryset(self): qs = CustomQuerySet(self.model) if self._db is not None: qs = qs.using(self._db) return qs
Django के व्यवस्थापक इंटरफ़ेस में कई डेटाबेस एक्सपोज़ करना
Django के व्यवस्थापक के पास कई डेटाबेस के लिए कोई स्पष्ट समर्थन नहीं है।
यदि आप अपने राउटर श्रृंखला द्वारा निर्दिष्ट डेटाबेस के अलावा किसी मॉडल पर एक व्यवस्थापक इंटरफ़ेस प्रदान करना चाहते हैं, तो आपको कस्टम
ModelAdmin
वर्ग लिखना होगा जो व्यवस्थापक को सामग्री के लिए एक विशिष्ट डेटाबेस का उपयोग करने के लिए निर्देशित करेगा।
ModelAdmin
ऑब्जेक्ट्स में पाँच तरीके होते हैं जिनके लिए कई-डेटाबेस समर्थन के लिए अनुकूलन की आवश्यकता होती है:
class MultiDBModelAdmin(admin.ModelAdmin): # A handy constant for the name of the alternate database. using = 'other' def save_model(self, request, obj, form, change): # Tell Django to save objects to the 'other' database. obj.save(using=self.using) def delete_model(self, request, obj): # Tell Django to delete objects from the 'other' database obj.delete(using=self.using) def get_queryset(self, request): # Tell Django to look for objects on the 'other' database. return super().get_queryset(request).using(self.using) def formfield_for_foreignkey(self, db_field, request, **kwargs): # Tell Django to populate ForeignKey widgets using a query # on the 'other' database. return super().formfield_for_foreignkey(db_field, request, using=self.using, **kwargs) def formfield_for_manytomany(self, db_field, request, **kwargs): # Tell Django to populate ManyToMany widgets using a query # on the 'other' database. return super().formfield_for_manytomany(db_field, request, using=self.using, **kwargs)
यहां प्रदान किया गया कार्यान्वयन एक बहु-डेटाबेस रणनीति को लागू करता है जहां किसी विशेष प्रकार की सभी वस्तुओं को एक विशिष्ट डेटाबेस पर संग्रहीत किया जाता है (उदाहरण के लिए, सभी
User
ऑब्जेक्ट
other
डेटाबेस में हैं)।
यदि आपके कई डेटाबेस का उपयोग अधिक जटिल है, तो आपके
ModelAdmin
को उस रणनीति को प्रतिबिंबित करने की आवश्यकता होगी।
InlineModelAdmin
ऑब्जेक्ट्स को एक समान फैशन में संभाला जा सकता है।
उन्हें तीन अनुकूलित तरीकों की आवश्यकता होती है:
class MultiDBTabularInline(admin.TabularInline): using = 'other' def get_queryset(self, request): # Tell Django to look for inline objects on the 'other' database. return super().get_queryset(request).using(self.using) def formfield_for_foreignkey(self, db_field, request, **kwargs): # Tell Django to populate ForeignKey widgets using a query # on the 'other' database. return super().formfield_for_foreignkey(db_field, request, using=self.using, **kwargs) def formfield_for_manytomany(self, db_field, request, **kwargs): # Tell Django to populate ManyToMany widgets using a query # on the 'other' database. return super().formfield_for_manytomany(db_field, request, using=self.using, **kwargs)
एक बार जब आप अपनी मॉडल व्यवस्थापक परिभाषाएँ लिख लेते हैं, तो उन्हें किसी भी
Admin
उदाहरण के साथ पंजीकृत किया जा सकता है:
from django.contrib import admin # Specialize the multi-db admin objects for use with specific models. 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)
यह उदाहरण दो व्यवस्थापक साइट सेट करता है।
पहली साइट पर,
Author
और
Publisher
वस्तुएं उजागर होती हैं;
Publisher
वस्तुओं में उस प्रकाशक द्वारा प्रकाशित पुस्तकों को दर्शाने वाली सारणीबद्ध इनलाइन होती है।
दूसरी साइट केवल प्रकाशकों को उजागर करती है, बिना इनलाइन के।
कई डेटाबेस के साथ कच्चे कर्सर का उपयोग करना
यदि आप एक से अधिक डेटाबेस का उपयोग कर रहे हैं, तो आप किसी विशिष्ट डेटाबेस के लिए कनेक्शन (और कर्सर) प्राप्त करने के लिए
django.db.connections
का उपयोग कर सकते हैं।
django.db.connections
एक शब्दकोश जैसी वस्तु है, जो आपको इसके उपनाम का उपयोग करके एक विशिष्ट कनेक्शन प्राप्त करने की अनुमति देती है:
from django.db import connections with connections['my_db_alias'].cursor() as cursor: ...
कई डेटाबेस की सीमाएँ
क्रॉस-डेटाबेस संबंध
Django वर्तमान में विदेशी कुंजी या कई-से-कई रिश्तों को कई डेटाबेसों के लिए कोई समर्थन प्रदान नहीं करता है। यदि आपने राउटर का उपयोग विभिन्न डेटाबेस में विभाजन को करने के लिए किया है, तो उन मॉडलों द्वारा परिभाषित किसी भी विदेशी कुंजी और कई-से-कई संबंध एकल डेटाबेस के लिए आंतरिक होने चाहिए।
यह संदर्भात्मक अखंडता के कारण है। दो वस्तुओं के बीच संबंध बनाए रखने के लिए, Django को यह जानना होगा कि संबंधित वस्तु की प्राथमिक कुंजी वैध है। यदि प्राथमिक कुंजी को एक अलग डेटाबेस पर संग्रहीत किया जाता है, तो प्राथमिक कुंजी की वैधता का आसानी से मूल्यांकन करना संभव नहीं है।
यदि आप InnoDB के साथ Postgres, Oracle, या MySQL का उपयोग कर रहे हैं, तो इसे डेटाबेस अखंडता स्तर पर लागू किया जाता है - डेटाबेस स्तर की मुख्य बाधाएं उन संबंधों के निर्माण को रोकती हैं जिन्हें मान्य नहीं किया जा सकता है।
हालाँकि, यदि आप MyISAM तालिकाओं के साथ SQLite या MySQL का उपयोग कर रहे हैं, तो कोई लागू संदर्भात्मक अखंडता नहीं है; नतीजतन, आप विदेशी डेटाबेस को 'नकली' पार करने में सक्षम हो सकते हैं। हालाँकि, यह कॉन्फ़िगरेशन आधिकारिक रूप से Django द्वारा समर्थित नहीं है।
कंट्राब ऐप्स का व्यवहार
कई कंट्रिब ऐप्स में मॉडल शामिल हैं, और कुछ ऐप दूसरों पर निर्भर हैं। चूंकि क्रॉस-डेटाबेस रिश्ते असंभव हैं, इसलिए यह कुछ प्रतिबंध बनाता है कि आप इन मॉडलों को डेटाबेस में कैसे विभाजित कर सकते हैं:
-
sites.Site
,sites.Site
,sites.Site
औरsites.Site
हर एक को उपयुक्त राउटर को देखते हुए किसी भी डेटाबेस में स्टोर किया जा सकता है। -
auth
मॉडल -User
,Group
औरPermission
- एक साथ जुड़े हुए हैं औरContentType
से जुड़े हुए हैं, इसलिए उन्हें सामग्री डेटाबेस के समान डेटाबेस में संग्रहीत किया जाना चाहिए। -
admin
निर्भर करता है, इसलिए इसके मॉडल को डेटाबेस के समान डेटाबेस में होना चाहिए। -
flatpages
औरredirects
sites
पर निर्भरsites
, इसलिए उनके मॉडलsites
के समान डेटाबेस में होने चाहिए।
इसके अलावा, कुछ ऑब्जेक्ट्स स्वचालित रूप से बनाए जाते हैं जब
migrate
डेटाबेस में उन्हें रखने के लिए एक टेबल बनाता है:
-
एक डिफ़ॉल्ट
Site
, -
प्रत्येक मॉडल के लिए एक
ContentType
(उस डेटाबेस में संग्रहीत नहीं किए गए सहित), -
प्रत्येक मॉडल के लिए तीन
Permission
(उन डेटाबेस में संग्रहीत नहीं हैं सहित)।
कई डेटाबेस के साथ सामान्य सेटअप के लिए, इन ऑब्जेक्ट्स को एक से अधिक डेटाबेस में रखना उपयोगी नहीं है। सामान्य सेटअप में प्राथमिक / प्रतिकृति और बाहरी डेटाबेस से जुड़ना शामिल है। इसलिए, एक डेटाबेस राउटर लिखने की सिफारिश की जाती है जो इन तीन मॉडलों को केवल एक डेटाबेस में सिंक्रनाइज़ करने की अनुमति देता है। Contrib और तृतीय-पक्ष एप्लिकेशन के लिए समान दृष्टिकोण का उपयोग करें, जिन्हें कई डेटाबेस में अपनी तालिकाओं की आवश्यकता नहीं है।
चेतावनी
यदि आप एक से अधिक डेटाबेस में सामग्री प्रकारों को सिंक्रनाइज़ कर रहे हैं, तो ध्यान रखें कि उनकी प्राथमिक कुंजियाँ डेटाबेस में मेल नहीं खा सकती हैं। इससे डेटा भ्रष्टाचार या डेटा हानि हो सकती है।