无法通过模型实例访问管理器
Posted
技术标签:
【中文标题】无法通过模型实例访问管理器【英文标题】:Manager isn't accessible via model instances 【发布时间】:2011-04-21 21:52:42 【问题描述】:我正在尝试在另一个中获取模型对象实例,但我提出了这个错误:
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
【问题讨论】:
【参考方案1】:我刚刚遇到了与此错误类似的问题。回顾您的代码,它似乎也可能是您的问题。我认为您的问题是您将“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()
【讨论】:
【参考方案2】:对于 django
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', ...]
【讨论】:
谢谢,这个答案正是我一直在寻找的。我希望我能多次投票。我的用例是当您向抽象模型添加功能时,您将不知道(在此级别)最终模型类的名称。 或使用topic.__class__.objects.get(id=topic_id)
。
这是一个旧答案,但从 Django v1.10 开始,我不再看到这些私有方法。但是,self.__class__.objects
可以根据您的其他答案解决问题。【参考方案3】:
也可能是一对花括号过多引起的,例如
ModelClass().objects.filter(...)
而不是正确的
ModelClass.objects.filter(...)
有时当 bpython(或 IDE)自动添加括号时,我会遇到这种情况。
结果当然是一样的——你有一个实例而不是一个类。
【讨论】:
【参考方案4】:如果主题是一个 ContentType 实例(它不是),这会起作用:
topic.model_class().objects.filter(forum = forum)
【讨论】:
model_class()
是ContentType
模型的方法。其他模型实例,包括topic
,没有model_class
方法。
对不起,我一定是看错了问题。我试图解决一个看似相似的问题......【参考方案5】:
topic.__class__.objects.get(id=topic_id)
【讨论】:
从 Django v1.10 开始工作。 这个__class__
也适用于抽象模型中的方法,因为我们不知道后代类的实际名称。在这种情况下,我使用了self.__class__.objects.get
在models.py
模型上表现出色。 def get_object(self): return self.__class__.objects.get(...)
。将其用于GenericForeignKey
。【参考方案6】:
当您尝试通过模型的实例访问模型的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
,不适用于实例。有关详细信息,请参阅documentation for retrieving objects。金钱报价:
Managers
只能通过模型类而不是模型实例访问,以强制区分“表级”操作和“记录级”操作操作。
(已添加重点)
更新
请参阅下面来自@Daniel 的 cmets。对类名使用标题大小写是个好主意(不,你必须:P)。例如 Topic
而不是 topic
。无论您指的是实例还是类,您的类名都会引起一些混淆。由于Manager isn't accessible via <model> instances
非常具体,我能够提供解决方案。错误可能并不总是那么不言自明。
【讨论】:
然而,topic
似乎是实际的模型类,而不是根据他提供的代码的实例。
@Daniel:是的。然而,只有当您尝试使用实例访问 Manager
时,才会出现错误 Manager isn't accessible via Foo instances
。见源码:code.djangoproject.com/svn/django/trunk/django/db/models/…
确实,也许是另一个原因(除了“这是最佳实践”)不使用小写字母作为类名 :) 看起来他可能会使用 topic
作为局部实例变量并吹走对类的引用。
你应该用过topic.model_class().objects
你也可以使用topic.__class__.objects
。上面@Nimo 提到的model_class()
似乎不起作用以上是关于无法通过模型实例访问管理器的主要内容,如果未能解决你的问题,请参考以下文章
为啥需要下载管理器来利用通过 isp 从加利福尼亚的计算机访问弗吉尼亚的 ec2 实例提供的完整下载速度?