관리자는 모델 인스턴스를 통해 액세스 할 수 없습니다.


87

다른 인스턴스에서 모델 개체 인스턴스를 얻으려고하는데이 오류가 발생합니다.

 Manager isn't accessible via topic instance

내 모델은 다음과 같습니다.

class forum(models.Model):
    # Some attributs

class topic(models.Model):
    # Some attributs

class post(models.Model):
    # Some attributs

    def delete(self):
        forum = self.topic.forum
        super(post, self).delete()
        forum.topic_count = topic.objects.filter(forum = forum).count()

내 견해는 다음과 같습니다.

def test(request, post_id):
    post = topic.objects.get(id = int(topic_id))
    post.delete()

그리고 나는 얻는다 :

post.delete()
forum.topic_count = topic.objects.filter(forum = forum).count()
Manager isn't accessible via topic instances

답변:


126

문제의 오류 Manager는 모델의 인스턴스를 통해 모델 에 액세스하려고 할 때 발생 합니다. 당신이 사용하고 소문자 클래스 이름을. 이로 인해 오류가 인스턴스에 액세스하여 발생했는지 여부를 말하기가 어렵습니다 Manager. 이 오류를 일으킬 수있는 다른 시나리오는 알 수 topic없기 때문에 topic클래스 대신 모델 의 인스턴스를 가리 키도록 변수를 어떻게 든 혼합했다고 가정하고 진행 하고 있습니다 .

이 줄이 범인입니다.

forum.topic_count = topic.objects.filter(forum = forum).count()
#                   ^^^^^

다음을 사용해야합니다.

forum.topic_count = Topic.objects.filter(forum = forum).count()
#                   ^^^^^
#                   Model, not instance.

무엇이 잘못 되었나요? objectsA는 Manager이 아닌 경우에, 클래스 레벨에서 사용할 수 있습니다. 자세한 내용은 개체 검색에 대한 설명서를 참조 하십시오. 돈 견적 :

Managers"테이블 수준"작업과 "레코드 수준"작업을 분리하기 위해 모델 인스턴스가 아닌 모델 클래스를 통해서만 액세스 할 수 있습니다.

(강조 추가)

최신 정보

아래 @Daniel의 의견을 참조하십시오. 클래스 이름에 대한 제목 대소 문자를 사용하는 것이 좋습니다 (아니요, 반드시 : P해야합니다). 예를 들어 Topic대신 topic. 클래스 이름은 인스턴스 또는 클래스를 참조하는지에 따라 약간의 혼란을 야기합니다. Manager isn't accessible via <model> instances매우 구체적 이기 때문에 해결책을 제시 할 수 있습니다. 오류가 항상 자명하지 않을 수도 있습니다.


그러나 topic그가 제공 한 코드에 따른 인스턴스가 아닌 실제 모델 클래스 인 것으로 보입니다.
Daniel DiPaolo 2010 년

@ 다니엘 : 사실. 그러나 오류 Manager isn't accessible via Foo instancesManager인스턴스를 사용하여 액세스하려고 할 때만 가능 합니다. 소스 코드 참조 : code.djangoproject.com/svn/django/trunk/django/db/models/…
Manoj Govindan

4
실제로, 클래스 이름에 소문자를 사용하지 않는 또 다른 이유 ( "최선의 방법"이 아닌) :) 잠재적 topic으로 로컬 인스턴스 변수로 사용하고 클래스에 대한 참조를 날려 버리는 것처럼 보입니다 .
Daniel DiPaolo 2010 년

2
당신은 사용해야topic.model_class().objects
니모

7
당신은 또한 사용할 수 있습니다 topic.__class__.objects. 그것은 보일 수있을 것입니다 model_class()작동하지 않는 이상 @Nimo 언급
sleepycal

54
topic.__class__.objects.get(id=topic_id)

Django v1.10에서 작동합니다.
James

3
이것은 __class__하위 클래스의 실제 이름을 모르기 때문에 추상 모델 내의 메서드에서도 더 잘 작동합니다. 이 상황에서 나는 사용self.__class__.objects.get
Cometsong

33

장고 <1.10의 경우

topic._default_manager.get(id=topic_id)

이렇게 사용하면 안되지만. _default_manager 및 _base_manager는 비공개이므로 독점 기능에서 Manager를 사용하려는 경우와 같이 Topic 모델 내부에있는 경우에만 사용하는 것이 좋습니다.

class Topic(Model):
.
.
.
    def related(self)
        "Returns the topics with similar starting names"
        return self._default_manager.filter(name__startswith=self.name)

topic.related() #topic 'Milan wins' is related to:
# ['Milan wins','Milan wins championship', 'Milan wins by one goal', ...]

5
감사합니다.이 답변은 제가 찾고 있던 것입니다. 한 번 이상 투표 할 수 있으면 좋겠어요. 이것에 대한 나의 유스 케이스는 당신이 추상 모델에 기능을 추가 할 때입니다.이 단계에서는 최종 모델 클래스가 무엇인지 알 수 없습니다.
fadedbee

2
또는 topic.__class__.objects.get(id=topic_id).
Bentley4

1
이것은 오래된 대답이지만 Django v1.10에서는 더 이상 이러한 개인 메서드를 볼 수 없습니다. 그러나 self.__class__.objects다른 답변에 따라 트릭을 수행합니다.
James

5

한 쌍의 괄호로 인해 발생할 수도 있습니다.

ModelClass().objects.filter(...)

올바른 대신

ModelClass.objects.filter(...)

bpython (또는 IDE)이 자동으로 괄호를 추가 할 때 가끔 발생합니다.

물론 결과는 동일합니다. 클래스 대신 인스턴스가 있습니다.


0

topic이 ContentType 인스턴스 (아닌 경우)이면 작동했을 것입니다.

topic.model_class().objects.filter(forum = forum)

model_class()ContentType모델 의 방법입니다 . 을 포함한 다른 모델 인스턴스 topic에는 model_class메서드 가 없습니다 .
Alasdair

죄송합니다. 질문을 잘못 읽은 것 같습니다. 비슷해 보이는 질문을 해결하려고했습니다 ...
Nimo

0

이 오류와 비슷한 문제가 발생했습니다. 그리고 당신의 코드를 되돌아 보면 그것이 당신의 문제 일 수도있는 것 같습니다. 귀하의 문제는 "id"를 "int (topic_id)"와 비교하고 topic_id가 설정되지 않은 것입니다.

def test(request, post_id):
    post = topic.objects.get(id = int(topic_id))
    post.delete()

코드가 "topic_id"가 아닌 "post_id"를 사용해야한다고 생각합니다.

def test(request, post_id):
    post = topic.objects.get(id = int(post_id))
    post.delete()
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.