2012-03-21 19 views
10

मान लीजिए कि हमारे पास निम्नलिखित मॉडल हैं। मॉडल एक मेंDjango OneToOneField - मुझे किस मॉडल में इसे रखना चाहिए?

:

class A(Model): pass 
class B(Model): pass 

तो फिर वहाँ के बीच कोई अंतर नहीं है b = OneToOneField(B, related_name=A.__name__)

और

मॉडल बी में

: a = OneToOneField(A, related_name=B.__name__)

तो क्या सवाल मैं अपने आप को पूछना तय करने के लिए करना चाहिए ओटीओ को एक मॉडल या दूसरे में रखना है या नहीं। मेरा मतलब है कि ए-ए, इज़-ए और इसी तरह है।

उत्तर

1

मुझे लगता है कि वनटोन क्षेत्र का मामला है, सही जवाब यह है कि इससे कोई फर्क नहीं पड़ता, यह केवल उस मॉडल पर निर्भर करता है जिस पर यह दूसरे से संबंधित है।

+0

ठीक है, यही सवाल है।मुझे कैसे पता चलेगा कि क्या अधिक समझ में आता है? कभी-कभी कोई अंतर नहीं होता है और दोनों तरीके समान रूप से संभव होते हैं। – aemdy

+0

इस तरह के उदाहरणों में, यह पूरी तरह से आपके ऊपर है। मुझे नहीं लगता कि एक निश्चित जवाब है। – Brandon

7

OneToOneField रों वास्तव में केवल दो उद्देश्यों के लिए कर रहे हैं: 1) विरासत (Django एमटीआई के इसके कार्यान्वयन) या 2) एक गैर-संपादन योग्य मॉडल का विस्तार (User के लिए एक UserProfile बनाने की तरह) के लिए इन का उपयोग करता है।

उन दो परिदृश्यों में, यह स्पष्ट है कि OneToOneField पर कौन सा मॉडल चल रहा है। विरासत के मामले में, यह बच्चे पर जाता है। विस्तार के मामले में यह आपके द्वारा उपयोग किए जाने वाले एकमात्र मॉडल पर जाता है।

बहुत कुछ अपवादों के साथ, एक-दूसरे के किसी अन्य उपयोग को वास्तव में केवल एक ही मॉडल में विलय किया जाना चाहिए।

+0

ग्रेट उत्तर क्रिस। – Brandon

+0

टेबल लॉकिंग के बारे में क्या? अगर हम विशिष्ट डेटा (जैसे कर्मचारी तालिका से वेतन तालिका) को अलग करना चाहते थे, तो हम वेतन तालिका को लॉक किए बिना कर्मचारी तालिका पर 'select_for_update' का उपयोग कर सकते थे। सही बात? – grokpot

23

वास्तव में एक अंतर है जहां आप एक-से-एक फ़ील्ड डालते हैं, क्योंकि विलोपन अलग-अलग व्यवहार करता है। जब आप किसी ऑब्जेक्ट को हटाते हैं, तो उस ऑब्जेक्ट को संदर्भित करने वाले एक-दूसरे संबंधों में से किसी एक ऑब्जेक्ट को हटा दिया जाएगा। यदि इसके बजाय आप एक ऑब्जेक्ट को हटाते हैं जिसमें एक-से-एक फ़ील्ड होता है (यानी यह अन्य ऑब्जेक्ट्स का संदर्भ देता है, लेकिन अन्य ऑब्जेक्ट्स इसे वापस संदर्भित नहीं कर रहे हैं), कोई अन्य ऑब्जेक्ट हटा नहीं जाता है।

उदाहरण के लिए:

class A(models.Model): 
    pass 

class B(models.Model): 
    a = models.OneToOneField(A) 

आप एक हटाते हैं, तो डिफ़ॉल्ट बी द्वारा के रूप में अच्छी तरह से हटा दिया जाएगा (हालांकि आप यह सिर्फ ForeignKey साथ की तरह OneToOneField पर on_delete तर्क को संशोधित करके ओवरराइड कर सकते हैं)। बी हटाने से ए को हटाया नहीं जाएगा (हालांकि आप बी पर डिलीट() विधि को ओवरराइड करके इस व्यवहार को बदल सकते हैं।

आपके शुरुआती प्रश्न पर वापस आना एक बनाम है- ए, यदि ए में बी है, बी में एक-एक-एक फ़ील्ड होना चाहिए (बी केवल अस्तित्व में होना चाहिए, लेकिन ए अस्तित्व में हो सकता है बी)।

0

वैसे, मैं सर्कुलर निर्भरता (विरासत उपयोग) को रोकने के लिए OneToOneField की जरूरत:

Model A: 
    ... 
    current_choice = models.ForeignKey(B) 

Model B: 
    ... 
    parent = models.ForeignKey(A) 

इसका मतलब है, एक बी की जरूरत है परिभाषित किया जाना है। बूटस्ट्रैपिंग के लिए एक अच्छा डेटाबेस सम्मेलन नहीं है। इसके बजाय मैंने किया:

Model A: 
    ... 

Model B: 
    ... 
    parent = models.ForeignKey(A) 

Model C: 
    parent = models.OneToOneField(A) 
    current_choice = models.ForeignKey(B) 

documentation से उदाहरण के लिए सम्मान के साथ, आप भी साफ प्रश्नों की तरह हो सकता है: p1.restaurant.place.restaurant.place ... यह पागलपन है।

+0

विदेशी कुंजी पर * related_name * का उपयोग करके आपको इस व्यवहार का एहसास क्यों नहीं हुआ? तो मॉडल ए पर आप 'current_choice = models.ForeignKey (बी, related_name =' parent ')' और फिर बी के प्रत्येक उदाहरण ('b = bobjects.first() ') पर कर सकते हैं, आप' b.parent कर सकते हैं संबंधित ए-ऑब्जेक्ट लाने के लिए। – Kim

+0

ठीक है, 'related_name' जरूरी नहीं है, लेकिन ज्यादातर समय एक सेट क्वेरी के रूप में उपयोग किया जाता है, इसलिए आपको गिनती आदि की जांच की आवश्यकता है। ऊपर उदाहरण एक तत्काल प्रश्न है क्योंकि इसे एक परिणाम देने के लिए मजबूर किया गया है केवल। – hurturk

संबंधित मुद्दे