2013-08-17 4 views
14

इन कार्यान्वयन के बीच अंतर क्या है? Django अलग-अलग क्या करता है (मेटा ordering और get_latest_by विशेषता विरासत के अलावा)?मल्टी-टेबल विरासत मॉडल के बीच क्या अंतर है और एक ही दो मॉडल के बीच एक-एक-एक संबंध है?

1.

# models.py 
from django.db import models 

class Place(models.Model): 
    name = models.CharField(max_length=50) 

class Restaurant(models.Model): 
    place = models.OneToOneField(Place) 
    serves_pizza = models.BooleanField() 

2.

class Place(models.Model): 
    name = models.CharField(max_length=50) 

class Restaurant(Place): 
    serves_pizza = models.BooleanField() 

3.

class Place(models.Model): 
    name = models.CharField(max_length=50) 

class Restaurant(Place): 
    place = models.OneToOneField(Place, parent_link=True) 
    serves_pizza = models.BooleanField() 
+0

मैं अतिरिक्त फ़ील्ड के साथ निर्मित साइट फ्रेमवर्क साइट मॉडल का विस्तार करना चाहता हूं और यह तय करने का प्रयास कर रहा हूं कि कौन सी विधि सर्वोत्तम है। – kissgyorgy

उत्तर

17

1. आप वास्तव में किसी भी अजगर विरासत नहीं मिलता है, वह यह है कि सूचीबद्ध कर सकते हैं का उपयोग करते हुए मॉडल सामग्री प्रकार के साथ विरासत आप के वारिस नहीं कर सकता/ओवरराइड तरीकों या अपने वर्ग Restaurant में मॉडल वर्ग Place से जिम्मेदार बताते हैं:

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

class Place(models.Model): 
    name = models.CharField(max_length=50) 

    def get_x(self): 
     return 'x' 

class Restaurant(models.Model): 
    place = models.OneToOneField(Place) 
    serves_pizza = models.BooleanField() 

a_restaurant = Restaurant() 
a_restaurant.get_x() # -> wouldn't work 

इसका मतलब है कि प्राप्त करने के लिए एक रेस्तरां आप ऐसा नहीं कर सकते a_restaurant.name की name, आप लिंक का पालन करने की आवश्यकता होगी: a_restaurant.place.name

भी ध्यान रखें कि जब संबंधित Restaurant के साथ एक Place वस्तु की क्वेरी।

a_restaurant.save() 
Place.objects.get(pk=a_restaurant.pk) # won't work 

आप लिखने के लिए होगा:

a_restaurant.save() 
Place.objects.get(restaurant__pk=a_restaurant.pk) 

2 और 3। लगभग एक ही हैं। आप इनके साथ असली पायथन विरासत प्राप्त करते हैं।

a_restaurant = Restaurant() 
a_restaurant.get_x() # would actually work and print 'x' 

आपका मॉडल वर्ग RestaurantPlace से सब कुछ विरासत में: मॉडल क्षेत्रों, सामान्य उदाहरण/वर्ग गुण, प्रबंधकों, तरीकों ... और आप भी लगभग इनमें से कुछ भी ओवरराइड कर सकते हैं: आप क्षेत्र विशेषताओं ओवरराइड नहीं कर सकते , यह समर्थित नहीं है।

तो अब आप मूल मॉडल से सीधे फ़ील्ड के मान प्राप्त कर सकते हैं: a_restaurant.name क्योंकि वे विरासत में हैं।

a_restaurant.save() 
the_place = Place.objects.get(pk=a_restaurant.pk) 
#^this works now and returns the equivalent `Place` instance. 
the_same_restaurant = the_place.restaurant 

अंतर 2 3 के बीच और यह देखने के लिए आसान है:

इन कार्यान्वयन के साथ के बाद से एक Restaurant एक भी Place आप Restaurant डेटा के साथ एक Place वस्तु के लिए क्वेरी कर सकते हैं आप फ़ील्ड में एक अलग नाम देते हैं:

class Place(models.Model): 
    name = models.CharField(max_length=50) 

class Restaurant(Place): 
    where = models.OneToOneField(Place, parent_link=True) 
    serves_pizza = models.BooleanField() 

वर्क्स बिल्कुल वैसा ही है, लेकिन एक Restaurant की मूल जगह प्राप्त करने के लिए विशेषता नाम where है:

the_place = a_restaurant.where 

साथ हो गया होता:

the_place = a_restaurant.place_ptr 

ये मतलब है कि place = models.OneToOneField(Place, parent_link=True) केवल परिवर्तन पैरेंट मॉडल उदाहरण के लिंक का नाम। डिफ़ॉल्ट नाम '{lowercase_model_name}_ptr' है।


अंतिम उदाहरण:

साथ :

place1 = Place.objects.create(name='place_1') 
place2 = Place.objects.create(name='place_2') 
restaurant1 = Restaurant.objects.create(place=place1, serves_pizza=True) 

print Place.objects.all() # prints [place1, place2] 
print Restaurant.objects.all() # prints [restaurant1] 

साथ 2-3:

place1 = Place.objects.create(name='place_1') 
place2 = Place.objects.create(name='place_2') 
restaurant1 = Restaurant.objects.create(name='place_3', serves_pizza=True) 

print Place.objects.all() # prints [place1, place2, place3] 
print Restaurant.objects.all() # prints [restaurant1] 

आशा है कि ये मदद करता है। यह थोड़ा लंबा हो जाता है:/

+0

मेरी व्यक्तिगत राय: 2º विकल्प इस उदाहरण के लिए सबसे अच्छा कार्यान्वयन प्रतीत होता है क्योंकि 'रेस्तरां' वास्तव में 'प्लेस' है। –

+0

बहुत अच्छी व्याख्या, मुझे यह लंबे समय तक उम्मीद नहीं थी :) धन्यवाद! – kissgyorgy

+1

एक नोटिस: बच्चे मॉडल से OneToOneField के लिए डिफ़ॉल्ट नाम Django 1.5 में 'objectname.parentobject_ptr' (objectname.parentobject नहीं है) है। तो आप # 2 में 'a_restaurant.place_ptr' के साथ प्लेस से पूछ सकते हैं। लेकिन दूसरी तरह के आसपास (जगह से क्वेरी) यह है: 'a_place.restaurant' – kissgyorgy

3

1 - आप जगह बनाने की जरूरत रेस्तरां बनाने के लिए, के बाद रेस्तरां बनाने के लिए, के बाद से लिंक, 2 - फिर रेस्तरां बनाना, नई जगह बनाई गई और स्वचालित रूप से जुड़ा हुआ, 3 - यो आप जगह के लिए पैरेंट लिंक का नाम बदल दिया।

आप सभी कैफे, रेस्तरां, बार, आदि Place.objects.all पर बार-बार दोहराना()

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