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

Tho*_*rin 70 django django-models django-managers instances

我正试图在另一个中获取模型对象实例.我提出这个错误:

 Manager isn't accessible via topic instance
Run Code Online (Sandbox Code Playgroud)

这是我的模特:

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()
Run Code Online (Sandbox Code Playgroud)

这是我的观点:

def test(request, post_id):
    post = topic.objects.get(id = int(topic_id))
    post.delete()
Run Code Online (Sandbox Code Playgroud)

我得到:

post.delete()
forum.topic_count = topic.objects.filter(forum = forum).count()
Manager isn't accessible via topic instances
Run Code Online (Sandbox Code Playgroud)

Man*_*dan 103

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

这条线是罪魁祸首:

forum.topic_count = topic.objects.filter(forum = forum).count()
#                   ^^^^^
Run Code Online (Sandbox Code Playgroud)

你必须使用:

forum.topic_count = Topic.objects.filter(forum = forum).count()
#                   ^^^^^
#                   Model, not instance.
Run Code Online (Sandbox Code Playgroud)

出了什么问题?objectsManager在类级别可用,而不是实例.有关详细信息,请参阅检索对象文档.钱报价:

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

(重点补充)

更新

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

  • 你也可以使用`topic .__ class __.objects`.似乎@Nimo上面提到的`model_class()`不起作用 (6认同)
  • 实际上,也许另一个原因(除了"最佳实践"之外)不要对类名使用小写字母:)这似乎是他可能使用`topic`作为本地实例变量并且吹掉对类的引用. (4认同)
  • 你应该使用过`topic.model_class().objects` (3认同)

mih*_*icc 45

topic.__class__.objects.get(id=topic_id)
Run Code Online (Sandbox Code Playgroud)

  • 这个 `__class__` 也适用于抽象模型中的方法,因为我们不知道后代类的实际名称。在这种情况下,我使用了`self.__class__.objects.get` (3认同)

mih*_*icc 33

对于django <1.10

topic._default_manager.get(id=topic_id)
Run Code Online (Sandbox Code Playgroud)

虽然你不应该这样使用它._default_manager和_base_manager是私有的,所以只有当你在Topic模型中时才建议使用它们,就像你想在专有函数中使用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', ...]
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这个答案正是我一直在寻找的.我希望我能不止一次投票.我的用例就是当你在抽象模型中添加功能时,你不会知道(在这个级别)调用最终模型类的内容. (5认同)
  • 或者使用`topic .__ class __.objects.get(id = topic_id)`. (2认同)

Mar*_*kus 5

也可能是由于一对寄生虫过多引起的,例如

ModelClass().objects.filter(...)
Run Code Online (Sandbox Code Playgroud)

而不是正确的

ModelClass.objects.filter(...)
Run Code Online (Sandbox Code Playgroud)

有时在bpython(或IDE)自动添加括号时发生在我身上。

结果当然是一样的-您有一个实例而不是一个类。