get_object
возвращает объект (экземпляр вашей модели), а get_queryset
возвращает отображение объекта QuerySet на набор потенциально нескольких экземпляров вашей модели.В случае DetailView
(или фактически любого класса, который наследуется от SingleObjectMixin
, цель get_queryset
состоит в том, чтобы ограничить набор объектов, из которых вы попытаетесь получить свой экземпляр .
Если вы хотите показать подробности экземпляра, вы должны как-то указать Django, как извлечь этот экземпляр. По умолчанию, как указывает сообщение об ошибке, Django вызывает метод get_object
, который ищетпараметр pk
или slug
в URL. В первом примере, где в URL был pk
, Django удалось автоматически получить ваш экземпляр, так что все работало нормально. Во втором примере вы отвергли get_object
и вручную использовал id
, переданный в качестве параметра для извлечения объекта, что также сработало. Однако в третьем примере вы не предоставили метод get_object
, поэтому Django выполнил метод по умолчанию. SingleObjectMixin default *Метод 1017 * не нашел ни pk, ни slug, поэтому он потерпел неудачу.
Есть несколько способов исправить это:
1. Используйте pk
в URL
Самый простой - просто использовать код, который вы указали в первом примере.Я не знаю, почему вы были недовольны этим, это прекрасно.Если вы недовольны, объясните, пожалуйста, почему.
2.Переопределить get_object
Это второе решение, которое вы предоставили.Это излишне, потому что, если вы правильно сконфигурировали свой вид с правильными параметрами (как вы увидите в следующих альтернативах), Django позаботится о том, чтобы получить объект для вас.
3.Укажите параметр pk_url_kwarg
Если вы действительно хотите по какой-то причине использовать id
в URL, вы можете указать это, указав параметр pk_url_kwarg
:
class todoDetailView(DetailView):
model = models.todo
pk_url_kwarg = 'id'
4.Укажите опции slug_field
и slug_url_kwarg
[НЕ ДЕЛАЙТЕ ЭТОГО]
Это ужасное решение, потому что вы на самом деле используете не слаг, а идентификатор, но в теории это должно сработать.По сути, вы будете «обманывать» Django, используя поле id
, как если бы это был слизень.Я упоминаю об этом только потому, что вы явно задали вопрос об этих параметрах в своем вопросе.
class todoDetailView(DetailView):
model = models.todo
slug_field = 'id'
slug_url_kwarg = 'id'
Относительно вашего get_queryset
метода: в вашем примере он даже не выполняется, но в любом случаеон не работает, потому что он возвращает отдельный объект вместо набора запросов (это то, что делает objects.get
).Я думаю, вам, вероятно, вообще не нужен пользовательский метод get_queryset
.Это было бы полезно, например, если у вас была сложная система разрешений, в которой разные пользователи могут получать доступ только к другому подмножеству todo
объектов, что, как я полагаю, не в вашем случае.В настоящее время, если вы предоставите этот метод get_queryset
, даже если все остальное настроено правильно, вы получите ошибку.Вероятно, AttributeError говорит о том, что объект queryset
не имеет атрибута filter
(потому что на самом деле это будет объект todo
, а не объект QuerySet , как ожидает Django ).