2009-06-03 3 views
5

가능한 한이 방법을 시도해 보겠습니다.Django 모델 상속 w/custom 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() 

예는 정말 내가 원하는, 여기 나와 함께 갈 문제가되지 않습니다 다음 내가 가지고 있다고 할 수 있습니다. 이것의 목적은 모든 사람들을 참조 할 수있는 마스터 Person 테이블을 가질 수 있도록하는 것입니다.

필자는 Person의 뷰를 호출하고 각 클래스 유형에 대해 사용자 정의 방식으로 나열된 특정 세부 정보를 갖기를 원합니다. 이 작업을 수행하려면 사용자 정의 inclusion_tag를 사용하고 싶습니다.

people.html

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

people_extras.py은 -

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. 

나는 그것이 사람의 유형에 따라 올바른 템플릿을 호출하는 방법에 아무 생각이 templatetags.

나는이 같은 {%의 ifequal의 %}를 사용하여 템플릿으로이 작업을 수행하는 방법을 알아낼 수 없습니다 :

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

나는 내가 templatetags 위에서 쓴 길을 갔다. 그러나, 나는 그 사람의 유형을 결정하는 논리를 어디에 둘 것인지 몰라!

필자는 결국 Person 객체에서 일반 뷰를 사용할 수 있기를 바랍니다.

이 작업을 수행하는 데 훨씬 좋은 방법이 있다면 제안을 받아 들일 수 있습니다. 작동하도록하고 싶습니다.

나는 하루 종일 여기 머물렀다. 정말로 밀어 넣을 수 있었다.

답변

5

Person 테이블에서 쿼리 한 후 올바른 사람 유형 하위 오브젝트를 얻는 효율적인 방법은 this answer을 참조하십시오.

일단 작업을 완료하면 다형성을 사용하여 템플릿 태그의 복잡성 대부분을 제거 할 수 있어야합니다. 다른 템플리트를 사용하여 각 개인 유형을 표시하려면 해당 템플리트 이름을 모델의 클래스 속성으로 지정하거나 모델 이름을 기반으로 템플리트 이름을 person._meta.module_name을 사용하여 작성하십시오. 하나의 간단한 템플릿 태그는 어떤 하위 클래스가 존재하는지에 대한 세부 사항조차 모른 채 모든 사례를 포함 할 수 있어야합니다. EDIT이 단일 태그는 템플릿 이름을 동적으로 결정해야하기 때문에 inclusion_tag 데코레이터를 사용하여 등록 할 수 없습니다. 그것은 다시 떨어지는 하위 유형에 대한 특정 템플릿이 발견되지 않는 경우이 등 worker.html, 은퇴 사용 retired.html를 사용하여 작업자 렌더링

@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}) 

:하지만 그것은 simple_tag 데코레이터를 사용하여 쓰기 쉽다 기본 person.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-knowing-the- name/929982 # 929982 –

+1

rix가 내 의견을 바탕으로 스 니펫을 수정 했으므로 더 이상 주석을 지적 할 필요가 없습니다. –

+0

오, 이런, 나는 모든 - nighter의 꼬리 끝에 있었고 어떤 이유로 내 두뇌가 self.pk가 등록되지 않았다. 자아 : –

0

("if not self.id:"의 할당을 포장). 기본 모델에서 상속받은 많은 모델이 있습니다. 데이터베이스의 모든 것을 고유 한 코드 ("go code"라고합니다)로 액세스 할 수 있습니다. 부모 개체의 자식을 찾으려면 다음과 같이하십시오.

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 

나는 지저분하지만 잘 작동한다는 것을 알고 있습니다. 객체의 "유형"을 부모 객체 모델의 비정규 화 된 필드에 저장하기 때문에 한 번만 "찾기"만하면됩니다. 이렇게하면 데이터베이스의 히트와 필요한 CPU 작업이 줄어 듭니다. 그런 다음 save()를 재정의하여 생성시 객체 유형을 찾고 해당 필드에 저장합니다.

희망이 있습니다.

+0

이것은 일반적인 생각을 가지고 있지만 더 복잡하고 (느린) 그럴 필요가있다. 생성시에 이미 적절한 유형을 알고 있기 때문에 유형 목록을 반복하고 각각을 점검 할 필요가 없습니다. http://stackoverflow.com/questions/929029/how-do-i-access-the-child-classes-of-an-object-in-django-without-knowing-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 

그것은 당신에게 첫번째 관련 객체 (중 하나 노동자 또는 퇴직)을 반환합니다.