Менеджер недоступен через экземпляры модели
Я пытаюсь получить экземпляр объектов модели в другом. И я вызываю эту ошибку:
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
Возникающая ошибка возникает при попытке получить доступ к 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)