通过模型实例无法访问管理器

114 投票
8 回答
116705 浏览
提问于 2025-04-16 05:05

我想在一个模型对象中获取另一个模型对象的实例,但出现了这个错误:

无法通过主题实例访问管理器

这是我的模型:

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

8 个回答

33

对于 Django 版本小于 1.10

topic._default_manager.get(id=topic_id)

不过你不应该这样使用它。_default_manager 和 _base_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', ...]
77
topic.__class__.objects.get(id=topic_id)

当然可以!请把你想要翻译的内容发给我,我会帮你用简单易懂的语言解释清楚。

168

这个错误发生在你试图通过一个模型的实例去访问它的 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.

出错的原因是什么呢? objects 是一个在类级别可用的 Manager,而不是在实例上可用。想了解更多细节,可以查看 获取对象的文档。重要的内容是:

Managers 只能通过模型类访问,而不能通过模型实例访问,这样可以区分“表级别”的操作和“记录级别”的操作。

(强调部分)

更新

请查看 @Daniel 的评论。使用标题大小写来命名类名是个好主意(其实你必须这样做 :P),例如用 Topic 而不是 topic。你的类名可能会让人困惑,不知道你是在指一个实例还是一个类。因为 Manager isn't accessible via <model> instances 这个说法非常具体,所以我能给出解决方案。这个错误并不总是那么明显。

撰写回答