아동 수업의 이름을 알지 못하고 Django의 객체의 어린이 클래스에 어떻게 액세스합니까?

StackOverflow https://stackoverflow.com/questions/929029

  •  06-09-2019
  •  | 
  •  

문제

Django에서는 부모 수업과 여러 자식 수업이있을 때 일반적으로 ParentClass.childclass1_set 또는 parentclass.childclass2_set을 통해 자식에 액세스 할 수 있지만 원하는 특정 자식 클래스의 이름을 모르는 경우 어떻게해야합니까?

아동 수업 이름을 모르고 부모-> 아동 방향으로 관련 개체를 얻는 방법이 있습니까?

도움이 되었습니까?

해결책

(업데이트: Django 1.2 및 Newer의 경우 Reverse OnetoOnefield 관계 (따라서 상속 계층 구조)를 통해 select_related queries를 따를 수있는 새로운 경우 추가를 필요로하지 않는 더 나은 기술이 있습니다. real_type 부모 모델의 필드. 사용할 수 있습니다 상속 공장 에서 Django-Model-utils 프로젝트.)

이를 수행하는 일반적인 방법은 적절한 "리프"클래스의 콘텐츠 유형을 저장하는 상위 모델의 ContentType에 외국 키를 추가하는 것입니다. 이 없으면 상속 트리가 얼마나 큰지에 따라 인스턴스를 찾기 위해 자식 테이블에서 많은 쿼리를 수행해야 할 수도 있습니다. 한 프로젝트에서 수행 한 방법은 다음과 같습니다.

from django.contrib.contenttypes.models import ContentType
from django.db import models

class InheritanceCastModel(models.Model):
    """
    An abstract base class that provides a ``real_type`` FK to ContentType.

    For use in trees of inherited models, to be able to downcast
    parent instances to their child types.

    """
    real_type = models.ForeignKey(ContentType, editable=False)

    def save(self, *args, **kwargs):
        if not self._state.adding:
            self.real_type = self._get_real_type()
        super(InheritanceCastModel, self).save(*args, **kwargs)

    def _get_real_type(self):
        return ContentType.objects.get_for_model(type(self))

    def cast(self):
        return self.real_type.get_object_for_this_type(pk=self.pk)

    class Meta:
        abstract = True

이것은 재사용 가능하게하기 위해 추상적 인 기본 클래스로 구현됩니다. 이러한 방법과 FK를 특정 상속 계층에서 부모 클래스에 직접 넣을 수도 있습니다.

부모 모델을 수정할 수없는 경우이 솔루션은 작동하지 않습니다. 이 경우 모든 서브 클래스를 수동으로 확인하는 데 거의 고정되어 있습니다.

다른 팁

파이썬에서 ( "새로운 스타일") 클래스 X가 주어지면 (직접) 하위 클래스를 얻을 수 있습니다. X.__subclasses__(), 클래스 객체 목록을 반환합니다. ( "더 많은 자손"을 원한다면, 당신은 또한 __subclasses__ 파이썬에서 효과적으로 수행하는 방법에 대한 도움이 필요한 경우 직접 서브 클래스 등 각각에서 문의하십시오!).

일단 당신이 어떻게 든 아동의 관심을 식별 한 후에 (아마도 모든 아동 서브 클래스의 사례 등을 원한다면) getattr(parentclass,'%s_set' % childclass.__name__) 도움이 필요합니다 (아동 계급의 이름이 'foo', 이것은 액세스와 같습니다 parentclass.foo_set -- 그 이상도 이하도 아닌). 다시 말하지만, 설명이나 예제가 필요하면 문의하십시오!

Carl의 솔루션은 좋은 것입니다. 여기에 여러 관련 아동 수업이있는 경우 수동으로 수행하는 한 가지 방법이 있습니다.

def get_children(self):
    rel_objs = self._meta.get_all_related_objects()
    return [getattr(self, x.get_accessor_name()) for x in rel_objs if x.model != type(self)]

Django가 진화함에 따라 안정적으로 보장되지는 않지만 _Meta에서 함수를 사용하지만 트릭을 수행하고 필요한 경우 날짜에 사용할 수 있습니다.

내가 정말로 필요로하는 것은 다음과 같습니다.

컨텐츠 유형 및 상속 인식 관리자와의 모델 상속

그것은 나를 위해 완벽하게 작동했습니다. 그래도 다른 모든 분들께 감사드립니다. 나는 당신의 대답을 읽는 것만으로 많이 배웠습니다!

당신이 사용할 수있는 Django- 폴리 모어 그에 대한.

파생 클래스를 실제 유형으로 자동으로 캐스트 할 수 있습니다. 또한 Django 관리자 지원,보다 효율적인 SQL 쿼리 처리 및 프록시 모델, 인라인 및 Formset 지원을 제공합니다.

기본 원칙은 여러 번 재창조되는 것 같습니다 (Wagtail 's 포함 .specific, 이 게시물에 요약 된 예제). 그러나 N- 쿼리 문제가 발생하지 않도록하거나 관리자, 양식 세트/인라인 또는 타사 앱과 잘 통합하려면 더 많은 노력이 필요합니다.

여기 내 솔루션이 있습니다. 다시 사용합니다 _meta 따라서 안정적으로 보장되지 않습니다.

class Animal(models.model):
    name = models.CharField()
    number_legs = models.IntegerField()
    ...

    def get_child_animal(self):
        child_animal = None
        for r in self._meta.get_all_related_objects():
            if r.field.name == 'animal_ptr':
                child_animal = getattr(self, r.get_accessor_name())
        if not child_animal:
            raise Exception("No subclass, you shouldn't create Animals directly")
        return child_animal

class Dog(Animal):
    ...

for a in Animal.objects.all():
    a.get_child_animal() # returns the dog (or whatever) instance

django.db.models.fields.related.relatedmanager의 인스턴스 인 부모의 모든 필드를 찾을 수 있습니다. 당신의 예에서 당신이 말하는 어린이 수업은 서브 클래스가 아닌 것 같습니다. 오른쪽?

프록시를 사용한 대체 접근법을 찾을 수 있습니다 이 블로그 게시물. 다른 솔루션과 마찬가지로, 그것은 그 이점과 부채가 있으며, 이는 게시물의 끝에 매우 잘 적용됩니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top