Метод get_object

Метод get_object класса DetailView отвечает за извлечение объекта модели, который будет отображаться на странице. Он автоматически использует параметры из URL-адреса, определённые в маршрутизации. По умолчанию метод получает значение параметра 'pk' или 'slug' для идентификации записи. Метод можно переопределить в дочернем классе для добавления кастомной логики поиска, например, фильтрации по полю пользователя или обработки исключений.

Синтаксис

pythonclass MyDetailView(DetailView):
  model = MyModel

  def get_object(self, queryset=None):
    # Переопределение метода для кастомного получения объекта
    return super().get_object(queryset)

Пример . С использованием pk

Допустим, у нас есть модель 'Article' и мы хотим вывести статью по её идентификатору. Для этого в классе представления указываем модель, а метод get_object автоматически извлечёт объект по переданному параметру 'pk' из URL:

python# urls.py
from django.urls import path
from .views import ArticleDetailView

urlpatterns = [
  path('article/<int:pk>/', ArticleDetailView.as_view(), name='article-detail'),
]

# views.py
from django.views.generic import DetailView
from myapp.models import Article

class ArticleDetailView(DetailView):
  model = Article
  template_name = 'article_detail.html'
  context_object_name = 'article'

Результат выполнения кода при переходе по URL '/article/1/':

python"Object of type Article with pk=1 is retrieved"

Пример . С использованием slug

Если в URL вместо числового идентификатора используется текстовый идентификатор (слаг), то необходимо указать поле 'slug_field'. Метод get_object автоматически выполнит поиск по этому полю:

python# urls.py
from django.urls import path
from .views import ArticleSlugDetailView

urlpatterns = [
  path('article/<slug:slug>/', ArticleSlugDetailView.as_view(), name='article-slug-detail'),
]

# views.py
from django.views.generic import DetailView
from myapp.models import Article

class ArticleSlugDetailView(DetailView):
  model = Article
  slug_field = 'slug'
  slug_url_kwarg = 'slug'
  template_name = 'article_detail.html'
  context_object_name = 'article'

Результат выполнения кода при переходе по URL '/article/my-first-article/':

python"Object of type Article with slug='my-first-article' is retrieved"

Переопределение метода get_object

Переопределение метода get_object позволяет добавить дополнительную логику, например, фильтрацию по текущему пользователю или обработку ошибок. В этом примере мы возвращаем статью только если она опубликована и принадлежит текущему пользователю:

python# views.py
from django.views.generic import DetailView
from django.http import Http404
from myapp.models import Article

class CustomArticleDetailView(DetailView):
  model = Article
  template_name = 'article_detail.html'
  context_object_name = 'article'

  def get_object(self, queryset=None):
    # Получаем объект стандартным способом
    obj = super().get_object(queryset)

    # Дополнительные проверки
    if obj.status != 'published' or obj.author != self.request.user:
      raise Http404("Статья недоступна")

    return obj

Результат выполнения кода для авторизованного пользователя, который является автором статьи:

python"Article object with custom filtering applied"

Использование queryset в get_object

Метод get_object может принимать аргумент 'queryset', который позволяет задать кастомный набор записей для поиска. Это полезно, если необходимо применить предварительную фильтрацию или оптимизацию запросов:

python# views.py
from django.views.generic import DetailView
from myapp.models import Article

class QuerysetArticleDetailView(DetailView):
  model = Article
  template_name = 'article_detail.html'
  context_object_name = 'article'

  def get_queryset(self):
    # Базовый набор записей с оптимизацией
    return Article.objects.select_related('author').filter(status='published')

  def get_object(self, queryset=None):
    # Используем переданный queryset или получаем его через метод
    if queryset is None:
      queryset = self.get_queryset()

    # Получаем идентификатор из URL
    pk = self.kwargs.get('pk')
    if pk is not None:
      return queryset.get(pk=pk)

    # Альтернативно по slug
    slug = self.kwargs.get('slug')
    if slug is not None:
      return queryset.get(slug=slug)

    raise Http404("Не удалось найти объект")

Результат выполнения кода при запросе с параметром 'pk=5':

python"Article object with author data prefetched"

Смотрите также

  • класс DetailView,
    который использует метод get_object для отображения деталей объекта
  • функция get_object_or_404,
    которая извлекает объект или возвращает ошибку 404
  • класс ListView,
    который выводит список объектов, в отличие от детального просмотра
  • функция get_list_or_404,
    которая возвращает список объектов или страницу 404