Django detailview get_queryset и get_object - PullRequest
0 голосов
/ 28 сентября 2018

Я использую Django detailview.Первоначально я использовал шаблон URL

url(r'^todo/details/(?P<pk>[\d]+)', views.todoDetailView.as_view(), name='detail_todo'),

Мой взгляд

class todoDetailView(DetailView):
model = models.todo

Он работал нормально.

Во втором случае мой URL

url(r'^todo/details/(?P<id>[\d]+)', views.todoDetailView.as_view(), name='detail_todo'),

на этот раз я изменил свой вид на

class todoDetailView(DetailView):
model = models.todo
# context_object_name = 'todo_detail'

 def get_object(self, **kwargs):
    print(kwargs)
    return models.todo.objects.get(id=self.kwargs['id'])

Все заработало, я изменил второй случай на

class todoDetailView(DetailView):
model = models.todo
# context_object_name = 'todo_detail'

def get_queryset(self):
    return models.todo.objects.get(id=self.kwargs['id'])

, затем я получаю ошибку,

Общий подробный вид todoDetailView должен вызываться либо с объектом pk, либо с слагом.

Я знаю, что нет подходящего слаг или pk.Итак, изначально я добавил get_object () (это работало), но get_queryset () не работает.В чем разница в их работе ??

А также, если пользователь получает данные только на основе слаг, я прочитал в StackOverflow, что

это можно использовать

slug_field = 'param_name'
slug_url_kwarg = 'param_name'

ссылка - Общий подробный вид ProfileView должен вызываться либо с объектом pk, либо с слагом

Может кто-нибудь объяснить мне фактическую работу get_object () и get_queryset () (также get_slug_field () если возможно)

Наряду с условиями slug_field и slug_url_kwarg

Заранее спасибо

Ответы [ 3 ]

0 голосов
/ 28 сентября 2018

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

0 голосов
/ 28 сентября 2018

По умолчанию get_object для DetailView пытается извлечь объект, используя pk или slug из URL.Самое простое, что вам нужно сделать, это использовать (?P<pk>[\d]+) в шаблоне URL.

Когда вы переопределяете get_object, вы заменяете это поведение по умолчанию, поэтому вы не получаете никаких ошибок.

Когда вы переопределяете get_queryset, Django сначала запускает ваш get_queryset метод и получает набор запросов.Затем он пытается извлечь объект из этого набора запросов, используя pk или slug, и вы получите ошибку, потому что вы не используете ни один из них.

slug_field иslug_url_kwarg параметры определены в документах.slug_fields - это имя поля в модели, используемой для извлечения элемента, а slug_url_kwarg - это имя параметра в шаблоне URL.В вашем случае вы выбираете объект, используя первичный ключ (pk / id), поэтому вам не следует использовать ни один из этих параметров.

Для шаблона URL с (?P<id>[\d]+) выможет использовать pk_url_kwarg = 'id'.Это скажет Django извлечь объект, используя id из URL.Однако гораздо проще использовать ваш первый шаблон URL с (?P<pk>[\d]+), тогда вам не нужно переопределять ни один из перечисленных выше методов / атрибутов.

0 голосов
/ 28 сентября 2018

Я не могу помочь вам с тем, что сообщение об ошибке явно означает, но get_queryset используется в списках просмотра для получения нескольких объектов, в то время как get_object используется для получения одного объекта (то есть DetailView).

Если у вас есть ПК, который вы можете использовать для получения объекта, вам не нужно указывать поле слаг.Слаг-поле используется, чтобы отфильтровать объекты, когда у вас нет или вы не можете показать первичный ключ публично. Это дает лучшее объяснение поля слагов.

...