无法通过模型实例访问Manager


83

我正在尝试在另一个模型对象实例中获取此错误:

 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

Answers:


122

当您尝试Manager通过模型的实例访问模型的时,会引起问题的错误。您使用了小写的类名。这使得很难说错误是由实例访问Manageror引起的。由于未知其他可能导致此错误的情况,因此我假设您以某种方式混淆了topic变量,从而最终指向了一个实例。topic模型而不是类。

这是罪魁祸首:

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

您必须使用:

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

怎么了?objects是一种Manager可在类级别,而不是实例。有关详细信息,请参阅文档以获取对象。货币报价:

Managers是可访问通过模型类从模型实例,而不是,执行“表级”的操作和“记录级”操作之间的分离。

(添加了强调)

更新资料

请参阅下面@Daniel的评论。对类名使用标题大小写是个好主意(不,您必须:P)。例如Topic代替topic。无论是引用实例还是类,您的类名都会引起一些混乱。由于Manager isn't accessible via <model> instances非常具体,所以我可以提供解决方案。错误可能并不总是那么明显。


但是,topic确实是实际的模型类,而不是根据他提供的代码的实例。
Daniel DiPaolo 2010年

@Daniel:是的。但是,Manager isn't accessible via Foo instances仅当您尝试Manager使用实例访问时,该错误才可能出现。看到源代码:code.djangoproject.com/svn/django/trunk/django/db/models/...
马诺Govindan

4
确实,也许还有另一个原因(“最佳实践”除外)不对类名使用小写字母:)看来他可能将其topic用作局部实例变量,并且吹散了对该类的引用。
Daniel DiPaolo 2010年

2
您应该使用过topic.model_class().objects
Nimo

7
您也可以使用topic.__class__.objects。这似乎是model_class()由@Nimo上面提到不起作用
sleepycal

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

从Django v1.10开始工作。
詹姆斯

3
__class__对于抽象模型中的方法也更好,因为我们不知道后代类的实际名称。在这种情况下,我使用了self.__class__.objects.get
Cometsong

33

对于Django <1.10

topic._default_manager.get(id=topic_id)

虽然您不应该这样使用它。_default_manager和_base_manager是私有的,因此建议仅在主题模型内部使用它们,例如,当您想在专有函数中使用Manager时,可以这样说:

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
谢谢,这个答案正是我一直在寻找的。我希望我可以投票一次以上。我的用例是当您向抽象模型添加功能时,您将不知道(在此级别上)最终模型类是什么。
褪色的蜜蜂

2
或使用topic.__class__.objects.get(id=topic_id)
Bentley13年

1
这是一个旧答案,但是从Django v1.10开始,我不再看到这些私有方法。但是,请self.__class__.objects按照其他答案来解决问题。
詹姆斯,

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 2013年

抱歉,我一定是看错了问题。我试图解决一个看似相似的问题……
Nimo 2013年

0

我只是遇到了与此错误类似的问题。回顾一下您的代码,似乎也可能是您的问题。我认为您的问题是未设置“ id”与“ int(topic_id)”和topic_id的比较。

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

我猜你的代码应该使用“ post_id”而不是“ topic_id”

def test(request, post_id):
    post = topic.objects.get(id = int(post_id))
    post.delete()
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.