Диспетчер не доступен через экземпляры модели - PullRequest
64 голосов
/ 06 октября 2010

Я пытаюсь получить экземпляр объекта модели в другом.И я поднимаю эту ошибку:

 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

Ответы [ 6 ]

99 голосов
/ 06 октября 2010

Данная ошибка возникает, когда вы пытаетесь получить доступ к 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 является очень конкретным, я могу предложить решение. Ошибка не всегда может быть настолько очевидной.

43 голосов
/ 16 октября 2012
topic.__class__.objects.get(id=topic_id)
32 голосов
/ 11 апреля 2012

Для Джанго <1.10 </p>

topic._default_manager.get(id=topic_id)

Хотя вы не должны использовать это так. _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', ...]
4 голосов
/ 20 января 2016

Может также быть вызвано слишком большим количеством паратезов, например,

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

вместо правильного

ModelClass.objects.filter(...)

Иногда случается со мной, когда bpython (или IDE) автоматическидобавляет парантезы.

Результат, конечно, тот же - у вас есть экземпляр вместо класса.

0 голосов
/ 19 января 2019

У меня только что была проблема, похожая на эту ошибку. И, оглядываясь на ваш код, кажется, что это тоже может быть вашей проблемой. Я думаю, что ваша проблема в том, что вы сравниваете "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()
0 голосов
/ 09 июня 2013

если бы тема была экземпляром ContentType (а это не так), это сработало бы:

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