Django में एक-से-कई संबंध कैसे व्यक्त करें


167

मैं अभी अपने Django मॉडल को परिभाषित कर रहा हूं और मुझे एहसास हुआ कि OneToManyFieldमॉडल फ़ील्ड प्रकारों में कोई नहीं था । मुझे यकीन है कि ऐसा करने का एक तरीका है, इसलिए मुझे यकीन नहीं है कि मैं क्या याद कर रहा हूं। मैं अनिवार्य रूप से कुछ इस तरह से है:

class Dude(models.Model):
    numbers = models.OneToManyField('PhoneNumber')

class PhoneNumber(models.Model):
    number = models.CharField()

इस मामले में, प्रत्येक Dudeएकाधिक हो सकता PhoneNumberहै, लेकिन संबंध, दिशाहीन होना चाहिए में है कि मैं से जानने की जरूरत नहीं है PhoneNumberजो Dudeयह मालिक है, दर असल, जैसा कि मैंने कई अलग अलग वस्तुओं हो सकता है खुद PhoneNumberइस तरह के एक के रूप में उदाहरणों, Businessके लिए उदाहरण:

class Business(models.Model):
    numbers = models.OneToManyField('PhoneNumber')

मैं क्या जगह लेंगे OneToManyField(जो मौजूद नहीं है) मॉडल संबंध इस तरह का प्रतिनिधित्व करने के लिए में साथ? मैं हाइबरनेट / जेपीए से आ रहा हूं जहां एक-से-कई संबंधों की घोषणा करना उतना ही आसान था:

@OneToMany
private List<PhoneNumber> phoneNumbers;

मैं इसे Django में कैसे व्यक्त कर सकता हूं?

जवाबों:


133

Django में एक-से-कई रिश्तों को संभालने के लिए आपको उपयोग करने की आवश्यकता है ForeignKey

फॉरेनके पर प्रलेखन बहुत व्यापक है और आपको अपने सभी सवालों के जवाब देने चाहिए:

https://docs.djangoproject.com/en/dev/ref/models/fields/#foreignkey

आपके उदाहरण में वर्तमान संरचना प्रत्येक दोस्त को एक नंबर, और प्रत्येक संख्या को कई दोस्तों (व्यवसाय के साथ समान) से संबंधित होने की अनुमति देती है।

यदि आप रिवर्स रिलेशनशिप चाहते हैं, तो आपको अपने फोननंबर मॉडल में दो फॉरेनके फील्ड्स जोड़ने होंगे, एक ड्यूड और एक बिजनेस। यह प्रत्येक संख्या को एक ड्यूड या एक व्यवसाय से संबंधित होने की अनुमति देगा, और इसमें कई संख्याओं के स्वामी और व्यवसाय हैं। मुझे लगता है कि यह वही हो सकता है जिसके बाद आप हैं।

class Business(models.Model):
    ...
class Dude(models.Model):
    ...
class PhoneNumber(models.Model):
    dude = models.ForeignKey(Dude)
    business = models.ForeignKey(Business)

3
क्या आप मुझे एक उदाहरण दे सकते हैं जो ऊपर दी गई समस्या है? मैं शायद इसे पूरी तरह से याद कर रहा हूं, लेकिन मैं पिछले कुछ समय से Django के दस्तावेज़ पढ़ रहा हूं और अभी भी स्पष्ट नहीं हूं कि इस तरह के संबंध कैसे बनाएं।
Naftuli Kay

4
हो सकता है कि दोनों विदेशियों को आवश्यकता न हो (रिक्त = सत्य, अशक्त = सत्य), या यह सुनिश्चित करने के लिए कि किसी तरह का कस्टम सत्यापन है, कम से कम एक या दूसरे को जोड़ना चाहते हैं। एक सामान्य संख्या वाले व्यवसाय के मामले के बारे में क्या? या एक बेरोजगार दोस्त?
j_syk 23

1
कस्टम सत्यापन के बारे में @j_syk अच्छा बिंदु। लेकिन ऐसा लगता है कि एक विदेशी को दोस्त और एक विदेशी को व्यापार में शामिल करने के लिए हैक की तरह लगता है, और फिर कस्टम (मॉडल परिभाषा के लिए बाहरी) सत्यापन करते हैं। ऐसा लगता है कि एक क्लीनर रास्ता होना चाहिए, लेकिन मैं इसका पता नहीं लगा सकता।
andy

इस स्थिति में ContentTypes Framework का उपयोग करना उचित है जो विभिन्न वस्तुओं के लिए सामान्य संबंधों की अनुमति देता है। हालांकि, सामग्री प्रकारों का उपयोग करना बहुत जल्दी बहुत जटिल हो सकता है, और यदि यह आपकी एकमात्र आवश्यकता है, तो यह सरल (यदि हैकी) दृष्टिकोण वांछनीय हो सकता है।
kball

57
उल्लेख करने के लिए एक प्रासंगिक बात फॉरेनके का "संबंधित_नाम" तर्क है। तो PhoneNumber वर्ग में आपके पास होगा dude = models.ForeignKey(Dude, related_name='numbers')और फिर आप some_dude_object.numbers.all()सभी संबंधित नंबरों पर प्राप्त करने के लिए उपयोग कर सकते हैं (यदि आप "संबंधित_नाम" निर्दिष्ट नहीं करते हैं तो यह "number_set" के लिए डिफ़ॉल्ट होगा)।
मार्कशीट

40

Django में, एक-से-कई संबंधों को फॉरेनके कहा जाता है। यह केवल एक ही दिशा में काम करता है, हालाँकि, आपको numberकक्षा की एक विशेषता होने के बजाय Dudeइसकी आवश्यकता होगी

class Dude(models.Model):
    ...

class PhoneNumber(models.Model):
    dude = models.ForeignKey(Dude)

कई मॉडल एक हो सकता है ForeignKeyएक अन्य मॉडल के लिए, तो यह की एक दूसरी विशेषता है करने के लिए वैध होगा PhoneNumberकि इस तरह के

class Business(models.Model):
    ...
class Dude(models.Model):
    ...
class PhoneNumber(models.Model):
    dude = models.ForeignKey(Dude)
    business = models.ForeignKey(Business)

आप उपयोग कर सकते हैं PhoneNumberएक के लिए रों Dudeवस्तु dके साथ d.phonenumber_set.objects.all(), और फिर एक के लिए इसी तरह कर Businessवस्तु।


1
मैं इस धारणा के तहत था कि ForeignKey"वन-टू-वन।" अपने उपर्युक्त उदाहरण का उपयोग करते हुए, मेरे पास ऐसा अधिकार होना चाहिए, Dudeजिसमें कई PhoneNumbersअधिकार हों?
Naftuli Kay

6
मैंने इसे दर्शाने के लिए अपना उत्तर संपादित किया। हाँ। ForeignKeyयदि आप निर्दिष्ट करते हैं तो केवल एक-से-एक है ForeignKey(Dude, unique=True), इसलिए उपरोक्त कोड के Dudeसाथ आपको कई PhoneNumberएस मिलेंगे ।
16

1
@ पत्थर मारना - शुक्रिया, मैं यह जोड़ रहा था कि मेरी गलती का एहसास होने के बाद आपने टिप्पणी की। अनोखा = सच OneToOneField की तरह काम नहीं करता है, मेरा मतलब है कि यदि आप Unique = True निर्दिष्ट करते हैं तो ForeignKey केवल एक-से-एक संबंध का उपयोग करता है।
16

8
इसे करने के लिए +1 PhoneNumber। अब यह समझ में आने लगा है। ForeignKeyअनिवार्य रूप से कई-से-एक है, इसलिए आपको एक-से-कई पाने के लिए पीछे की ओर करने की आवश्यकता है :)
Naftuli Kay

2
क्या कोई क्षेत्र के नाम के महत्व को समझा सकता है phonenumber_set? मैं इसे कहीं भी परिभाषित नहीं देखता। क्या यह मॉडल का नाम है, सभी निचले मामलों में, "_set" के साथ जोड़ा गया?
जेम्स वेरजबा

20

अधिक स्पष्ट होने के लिए - Django में कोई OneToMany नहीं है, केवल ManyToOne - जो कि ऊपर वर्णित फॉरेनकी है। आप फॉरेनकी का उपयोग करके OneToMany संबंध का वर्णन कर सकते हैं लेकिन यह बहुत ही अनुचित है।

इसके बारे में एक अच्छा लेख: https://amir.rachum.com/blog/2013/06/15/a-case-for-a-onetomany-relationship-in-django/


आप ManyToManyField का उपयोग कर सकते हैं।
user5510975

15

आप या तो विदेशी कुंजी का उपयोग कर सकते हैं OneToManyसंबंध के कई पक्ष (यानी ManyToOneसंबंध) या उपयोग ManyToMany(किसी भी तरफ) अद्वितीय बाधा के साथ।


8

djangoकाफी होशियार है। वास्तव में हमें oneToManyक्षेत्र को परिभाषित करने की आवश्यकता नहीं है । यह स्वचालित रूप से आपके djangoलिए उत्पन्न होगा :-)। हमें केवल foreignKeyसंबंधित तालिका में परिभाषित करने की आवश्यकता है । दूसरे शब्दों में, हमें केवल ManyToOneउपयोग करके संबंध को परिभाषित करने की आवश्यकता है foreignKey

class Car(models.Model):
    // wheels = models.oneToMany() to get wheels of this car [**it is not required to define**].


class Wheel(models.Model):
    car = models.ForeignKey(Car, on_delete=models.CASCADE)  

अगर हम विशेष कार के पहियों की सूची प्राप्त करना चाहते हैं। हम python'sऑटो उत्पन्न वस्तु का उपयोग करेंगे wheel_set। कार के लिए cआप उपयोग करेंगेc.wheel_set.all()


5

जबकि पत्थर रोलिंग के जवाब अच्छा, सरल और कार्यात्मक है, मुझे लगता है कि दो चीजें इसे हल नहीं करता है।

  1. यदि ओपी एक फोन नंबर लागू करना चाहता था तो वह एक दोस्त और एक व्यवसाय दोनों से संबंधित नहीं हो सकता है
  2. फोननंबर मॉडल पर संबंध को परिभाषित करने और ड्यूड / बिजनेस मॉडल पर नहीं के परिणामस्वरूप दुख की अपरिहार्य भावना। जब अतिरिक्त टेरेस्ट्रिअल्स पृथ्वी पर आते हैं, और हम एक एलियन मॉडल जोड़ना चाहते हैं, तो हमें एलियन मॉडल में केवल "phone_numbers" फ़ील्ड जोड़ने के बजाय PhoneNumber (ETs फोन नंबर है) को संशोधित करने की आवश्यकता है।

सामग्री प्रकार के ढांचे का परिचय दें , जो कुछ वस्तुओं को उजागर करता है जो हमें PhoneNumber मॉडल पर "जेनेरिक विदेशी कुंजी" बनाने की अनुमति देता है। फिर, हम यार और व्यापार पर रिवर्स संबंध को परिभाषित कर सकते हैं

from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.db import models

class PhoneNumber(models.Model):
    number = models.CharField()

    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE)
    object_id = models.PositiveIntegerField()
    owner = GenericForeignKey()

class Dude(models.Model):
    numbers = GenericRelation(PhoneNumber)

class Business(models.Model):
    numbers = GenericRelation(PhoneNumber)

देखें डॉक्स जानकारी के लिए, और शायद बाहर की जाँच इस लेख एक त्वरित ट्यूटोरियल के लिए।

इसके अलावा, यहां एक लेख है जो जेनेरिक एफके के उपयोग के खिलाफ तर्क देता है ।


0

यदि "कई" मॉडल प्रति-मॉडल के निर्माण का औचित्य साबित नहीं करता है (यहां मामला नहीं है, लेकिन यह अन्य लोगों को लाभ दे सकता है), एक अन्य विकल्प Django कंट्रीब पैकेज के माध्यम से विशिष्ट PostgreSQL डेटा प्रकारों पर भरोसा करना होगा।

Postgres के साथ सौदा कर सकते हैं सरणी या JSON डेटा प्रकार, और यह एक अच्छा वैकल्पिक हल जब एक-से-अनेक संभालने के लिए हो सकता है कई-एँ केवल की एक इकाई से जुड़ी होती हैं एक

पोस्टग्रेज आपको सरणी के एकल तत्वों तक पहुंचने की अनुमति देता है, जिसका अर्थ है कि प्रश्न वास्तव में तेज़ हो सकते हैं, और एप्लिकेशन-स्तर ओवरहेड्स से बच सकते हैं। और हां, Django इस सुविधा का लाभ उठाने के लिए एक शांत एपीआई लागू करता है

यह स्पष्ट रूप से अन्य डेटाबेस बैकएंड के लिए पोर्टेबल नहीं होने का नुकसान है, लेकिन मैं अभी भी ध्यान देने योग्य है।

आशा है कि यह कुछ लोगों को विचारों की तलाश में मदद कर सकता है।


0

सबसे पहले हम एक यात्रा करते हैं:

01) एक-से-कई संबंध:

ASSUME:

class Business(models.Model):
    name = models.CharField(max_length=200)
    .........
    .........
    phone_number = models.OneToMany(PhoneNumber) (NB: Django do not support OneToMany relationship)

class Dude(models.Model):
    name = models.CharField(max_length=200)
    .........
    .........
    phone_number = models.OneToMany(PhoneNumber) (NB: Django do not support OneToMany relationship)

class PhoneNumber(models.Model):
    number = models.CharField(max_length=20)
    ........
    ........

NB: Django कोई OneToMany संबंध प्रदान नहीं करता है। इसलिए हम Django में ऊपरी विधि का उपयोग नहीं कर सकते। लेकिन हमें रिलेशनल मॉडल में बदलने की जरूरत है। तो हम क्या कर सकते हैं? इस स्थिति में हमें रिलेशनल मॉडल को रिवर्स रिलेशनल मॉडल में बदलने की आवश्यकता है।

यहाँ:

संबंधपरक मॉडल = OneToMany

तो, रिवर्स रिलेशनल मॉडल = ManyToOne

NB: Django ManyToOne संबंध का समर्थन करता है और Django में ManyToOne का प्रतिनिधित्व विदेशीके द्वारा किया जाता है।

02) कई-एक-एक संबंध:

SOLVE:

class Business(models.Model):
    .........
    .........

class Dude(models.Model):
    .........
    .........

class PhoneNumber(models.Model):
    ........
    ........
    business = models.ForeignKey(Business)
    dude = models.ForeignKey(Dude)

नायब: लगता है कि !!

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.