Manager isn't accessible via model instances

大兔子大兔子 提交于 2019-12-17 17:43:29

问题


i'm trying to get model objects instance in another one. And i raise this error :

 Manager isn't accessible via topic instance

Here's my model :

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()

Here's my view :

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

And i get :

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

回答1:


The error in question is caused when you try to access the Manager of a model through an instance of the model. You have used lower case class names. This makes it hard to say if the error is caused by an instance accessing the Manager or not. Since other scenarios that can cause this error are unknown I am proceeding on the assumption that you have somehow mixed up the topic variable so that you end up pointing to an instance of the topic model instead of the class.

This line is the culprit:

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

You have to use:

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

What is going wrong? objects is a Manager available at the class level, not to the instances. See the documentation for retrieving objects for details. Money quote:

Managers are accessible only via model classes, rather than from model instances, to enforce a separation between "table-level" operations and "record-level" operations.

(Emphasis added)

Update

See the comments from @Daniel below. It is a good idea (nay, you MUST :P) to use title case for class names. For instance Topic instead of topic. Your class names cause some confusion whether you are referring to an instance or a class. Since the Manager isn't accessible via <model> instances is very specific I am able to offer a solution.The error may not be so self evident always.




回答2:


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



回答3:


For django < 1.10

topic._default_manager.get(id=topic_id)

Though you should not use it like this. The _default_manager and _base_manager are private, so it's recomended to use them only if you're inside the Topic model, like when you want to use the Manager in a proprietary function let's say:

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', ...]



回答4:


Could also be caused by a pair of parantheses too much, e.g.

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

instead of the correct

ModelClass.objects.filter(...)

Happens to me sometimes when bpython (or an IDE) automatically adds parantheses.

The result, of course, is the same - you have an instance instead of a class.




回答5:


if topic were a ContentType instance (which it is not), this would have worked:

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



回答6:


I just had an issue similar to this error. And looking back at your code it seems that it could be your issue too. I think your issue is that your comparing "id" to "int(topic_id)" and topic_id is not set.

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

I'm guessing your code should use "post_id" not "topic_id"

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


来源:https://stackoverflow.com/questions/3874187/manager-isnt-accessible-via-model-instances

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!