Подтвердить что ты не робот

Менеджер недоступен через экземпляры модели

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

 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
4b9b3361

Ответ 1

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

(добавлен акцент)

Обновление

См. комментарии от @Даниэля ниже. Это хорошая идея (нет, вы ДОЛЖНЫ: P) использовать заголовок для имен классов. Например topic вместо topic. Названия классов вызывают некоторую путаницу в отношении того, ссылаетесь ли вы на экземпляр или класс. Поскольку Manager isn't accessible via <model> instances очень специфичен, я могу предложить решение. Ошибка может быть не всегда очевидной.

Ответ 2

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

Ответ 3

Для django < 1.10

topic._default_manager.get(id=topic_id)

Хотя вы не должны использовать его так. _default_manager и _base_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

Также может быть вызвана парами скобок, например,

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

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

ModelClass.objects.filter(...)

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

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

Ответ 5

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

Ответ 6

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

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