2009-06-03 10 views
5

मैं जितना संभव हो उतना प्रयास करने और इसे सरल बनाने वाला हूं।Django मॉडल विरासत w/कस्टम inclusion_tags

models.py

class Person(models.Model): 
    name = models.CharField(max_length=255) 

    def getRealPerson(self): 
     # is there a better way to do this? 
     ret = None 
     try: 
      ret = self.worker 
     except: 
      try: 
       ret = self.retired 
      except: 
       ret = self 
     return ret 
class Worker(Person): 
    salary = models.IntegerField(default=0) 

class Retired(Person): 
    age = models.IntegerField() 

उदाहरण वास्तव में कोई फर्क नहीं पड़ता के लिए मैं क्या चाहते हैं, बस यहाँ मेरे साथ जाना: कहते हैं कि मेरे पास है निम्नलिखित की सुविधा देता है। इसका उद्देश्य यह है कि मैं सभी लोगों के संदर्भ में एक मास्टर पर्सनल टेबल रख सकता हूं।

आदर्श रूप से मैं व्यक्तियों के विचार को कॉल करने में सक्षम होना चाहता हूं और प्रत्येक वर्ग प्रकार के लिए कस्टम तरीके से सूचीबद्ध प्रत्येक विशिष्ट विवरण प्राप्त करना चाहता हूं। मैं ऐसा करने के लिए एक कस्टम inclusion_tag का उपयोग करना चाहता हूँ।

people.html

{% load people_extras %} 
{% for person in people %} 
    {% show_person person %} 
{% endfor %} 

people_extras.py - templatetags

from django import template 

@register.inclusion_tag('worker.html') 
def show_worker(person): 
    return {'person':person} 

@register.inclusion_tag('worker.html') 
def show_retired(person): 
    return {'person':person} 

#How do I write this function and use it as the show_person person tag? 
from project.app.models import Worker, Retired 
def show_person(person): 
    person = person.getRealPerson(): 
    if isinstance(person, Worker): 
     return show_worker # yes, this doesn't work. 

मैं पता नहीं यह व्यक्ति प्रकार के आधार पर सही टेम्पलेट कॉल करने के लिए प्राप्त करने के लिए किया है।

मैं समझ नहीं सकता कैसे {% ifequal%} का उपयोग करते हुए इस तरह टेम्पलेट के साथ यह पूरा करने के:

{% ifequal person.getRealPerson.__class__.__name__ "Worker" %} 
    {% show_worker %} 
... 

मैं मार्ग मैं templatetags साथ ऊपर लिखा गया था। हालांकि, मुझे नहीं पता कि व्यक्ति का प्रकार निर्धारित करने के लिए तर्क कहां रखना है!

मुझे लगता है कि अंत में मैं व्यक्ति वस्तु के साथ-साथ इसके लिए एक सामान्य दृश्य का उपयोग करने में सक्षम होना चाहता हूं।

यदि ऐसा करने का एक बेहतर तरीका है, तो मैं सुझावों के लिए खुला हूं, मैं बस इसे काम करना चाहता हूं।

मैं यहाँ एक दिन से अधिक अटक गया हूं ... वास्तव में एक धक्का का उपयोग कर सकता है।

उत्तर

5

एक कारगर तरीका व्यक्ति मेज पर क्वेरी करने के बाद सही व्यक्ति प्रकार उप-वस्तु पाने के लिए this answer देखें।

एक बार जब आप काम कर रहे है कि है, तो आप बहुरूपता का उपयोग करके अपने टेम्पलेट टैग में जटिलता के सबसे खत्म करने के लिए सक्षम होना चाहिए। आप एक अलग टेम्पलेट का उपयोग कर प्रत्येक व्यक्ति प्रकार प्रदर्शित करने के लिए चाहते हैं, यह है कि टेम्पलेट का नाम मॉडल का एक वर्ग विशेषता बनाने या बस टेम्पलेट मॉडल नाम के आधार पर (person._meta.module_name का प्रयोग करके) नाम हैं। एक सरल टेम्पलेट टैग तब सभी मामलों को कवर करने में सक्षम होना चाहिए, यहां तक ​​कि बिना किसी सबक्लास मौजूद हैं। संपादित यह एकल टैग inclusion_tag डेकोरेटर का उपयोग कर, क्योंकि आप टेम्पलेट का नाम गतिशील निर्धारित करने के लिए की आवश्यकता होगी पंजीकृत नहीं किया जा सकता है। लेकिन यह simple_tag डेकोरेटर का उपयोग कर लिखने के लिए आसान है:

@register.simple_tag 
def show_person(person): 
    t = template.loader.select_template(["%s.html" % person._meta.module_name, 
             "person.html") 
    return t.render({'person': person}) 

यह worker.html, एक सेवानिवृत्त retired.html का उपयोग कर, आदि का उपयोग कर एक कार्यकर्ता प्रस्तुत करना होगा, तो उप-प्रकार के लिए विशिष्ट टेम्पलेट नहीं मिला है, इसे वापस गिर जाता है डिफ़ॉल्ट व्यक्ति.html पर।

+0

I देखें मैं इस के कस्टम टेम्पलेट टैग कार्यान्वयन पर थोड़ा उलझन में हूँ। testperson.cast() सही उप-ऑब्जेक्ट देता है, लेकिन मैं सही inclusion_tag को कॉल करने में इसका उपयोग कैसे कर सकता हूं। जिस तरह से मैंने इसे ऊपर सेट किया है, show_person को कॉल करने का कोई तरीका नहीं है (यह पंजीकृत नहीं है)। – lostincode

+0

यही है कि मैंने दूसरे पैराग्राफ में संबोधित किया। आशा है कि इसे स्पष्ट रूप से स्पष्ट करें। –

2

अपने मॉडल प्रकारों की पहचान के लिए Django के contenttypes framework का लाभ उठाएं।

इस स्निपेट देखें: Child aware model inheritance और टिप्पणियों में Carl Meyer's सुझाव का उपयोग

+0

या यह उत्तर देखें: http://stackoverflow.com/questions/929029/how-do-i-access-the-child-classes-of-an-object-in-django-without-now- the- नाम/929,982 # 929,982 –

+1

भी ध्यान रखें कि rix मेरे सुझाव के आधार पर उसका टुकड़ा तय है, तो यह अब टिप्पणी का कहना है करने के लिए आवश्यक है। –

+0

ओह दुह, मैं एक ऑल-नाइटर की पूंछ के अंत में था और किसी कारण से मेरा दिमाग self.pk को पंजीकृत नहीं कर रहा था self.id :) –

0

("if not self.id:" में काम लपेट) मैं एक विधि है कि मैं एक साथ इस समय जल्दी से काट दिया एक बहुत ही इसी तरह की काम करने के लिए इस्तेमाल करते हैं। मेरे पास मुख्य "आधार" मॉडल से विरासत में कई मॉडल हैं - मैं अपने डेटाबेस में एक अद्वितीय कोड द्वारा सबकुछ एक्सेस कर सकता हूं (हम इसे "कोड जाना" कहते हैं)। पैरेंट ऑब्जेक्ट के बच्चे जानने के लिए, मैं कुछ इस तरह करते हैं:

def get_child_types(self): 
    return [ c.__name__.lower() for c in self.__subclasses__() ] 

def get_child(self): 
    for type in self.get_child_types(): 
     try: 
      o = self.__getattribute__(type) 
     except: 
      pass 
     else: 
      return o 

मैं जानता हूँ कि यह गंदा है, लेकिन यह ठीक काम करता है। मैं ऑब्जेक्ट के "टाइप" को मूल ऑब्जेक्ट मॉडल में एक डिमॉर्मलाइज्ड फ़ील्ड में संग्रहीत करता हूं, इसलिए मुझे इसे कभी-कभी "ढूंढना" पड़ता है - जो डेटाबेस पर हिट को कम करता है और सीपीयू काम की आवश्यकता होती है। मैं फिर सृजन पर वस्तु प्रकार खोजने के लिए सहेजें() को ओवरराइड करता हूं, और उसे उस फ़ील्ड में संग्रहीत करता हूं।

उम्मीद है कि यह मदद करता है!

+0

इसका सामान्य सही विचार है, लेकिन यह अधिक जटिल (और धीमी) है इसकी आवश्यकता होने की तुलना में। निर्माण के समय में आप पहले से ही उचित प्रकार पता है, तो आप कभी भी प्रकार की एक सूची के माध्यम से पाशन और हर एक की जाँच करके यह पता लगाने के लिए की जरूरत नहीं है। Http://stackoverflow.com/questions/929029/how-do-i-access-the-child-classes-of-an-object-in-django-without-nownow-the-name/929982#929982 –

0

अपने getRealPerson() व्यक्ति मॉडल विधि के लिए इस स्निपेट का उपयोग:

def getRealPerson(self): 
    from django.db.models.fields.related import OneToOneRel 
    from django.core.exceptions import ObjectDoesNotExist 
    for related in self._meta.get_all_related_objects(): 
     rel_opts_name = related.get_accessor_name() 
     if isinstance(related.field.rel, OneToOneRel): 
      try: 
       sub_obj = getattr(self, rel_opts_name) 
      except ObjectDoesNotExist: 
       pass 
      else: 
       return sub_obj 

यह पहले आपको संबंधित वस्तु (या तो एक कार्यकर्ता या एक सेवानिवृत्त) वापस आ जाएगी।

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