Разработка представлений списка и детальной информации

⏱ 20 мин · 🧩 заданий: 5

Представления блога

View блога будут простыми функциями (позже переделаем на классы). blog/views.py:

from django.shortcuts import get_object_or_404, render

from .models import Post


def post_list(request):
    posts = Post.published.all()
    return render(request, "blog/post/list.html", {"posts": posts})


def post_detail(request, id):
    post = get_object_or_404(Post, id=id, status=Post.Status.PUBLISHED)
    return render(request, "blog/post/detail.html", {"post": post})

Почему фильтр по статусу и в detail

Если искать пост просто по id, любой, кто угадает номер, прочитает черновик. Поэтому ищем только среди опубликованных. Можно короче — передать менеджер:

post = get_object_or_404(Post.published, id=id)

Без get_object_or_404

Для понимания — то же самое вручную:

from django.http import Http404


def post_detail(request, id):
    try:
        post = Post.published.get(id=id)
    except Post.DoesNotExist:
        raise Http404("Пост не найден")
    return render(request, "blog/post/detail.html", {"post": post})

Маршруты

Создайте blog/urls.py:

from django.urls import path

from . import views

app_name = "blog"

urlpatterns = [
    path("", views.post_list, name="post_list"),
    path("<int:id>/", views.post_detail, name="post_detail"),
]

Подключите в mysite/urls.py:

from django.contrib import admin
from django.urls import include, path

urlpatterns = [
    path("admin/", admin.site.urls),
    path("blog/", include("blog.urls", namespace="blog")),
]

Пространство имён blog позволяет ссылаться на маршруты как blog:post_list и blog:post_detail, не боясь конфликтов с другими приложениями.

Канонический URL поста

Добавим в модель метод, возвращающий адрес поста:

from django.urls import reverse


class Post(models.Model):
    ...

    def get_absolute_url(self):
        return reverse("blog:post_detail", args=[self.id])

Теперь в шаблонах можно писать {{ post.get_absolute_url }}, а в админке появится кнопка «Смотреть на сайте». В уроке «Работа с URL» мы заменим адрес по id на красивый адрес с датой и слагом — и благодаря get_absolute_url ничего, кроме этого метода и маршрута, менять не придётся.

Проверим

Шаблонов ещё нет, поэтому /blog/ пока выдаст ошибку TemplateDoesNotExist — это нормально. Займёмся шаблонами в следующем уроке.

Итог

  • post_list — Post.published.all(), post_detail — get_object_or_404 среди опубликованных.
  • Маршруты приложения с app_name = "blog" подключаются через include().
  • get_absolute_url() — единое место, где определяется адрес поста.

Практика решено 0 из 5

Вы не вошли — ответы проверяются, но прогресс не сохранится. Войти или зарегистрироваться.
Задание 1 Написать код

Напишите view post_list, которая получает все опубликованные посты через менеджер published и рендерит blog/post/list.html с переменной posts.

Задание 2 Написать код

Напишите view post_detail(request, id), которая находит опубликованный пост по id (иначе 404) и рендерит blog/post/detail.html с переменной post.

Задание 3 Написать код

Напишите blog/urls.py: пространство имён blog, маршрут "" → post_list (имя post_list) и "<int:id>/" → post_detail (имя post_detail).

Задание 4 Один вариант ответа

Какой адрес у списка постов, если в mysite/urls.py написано path("blog/", include("blog.urls", namespace="blog"))?

Задание 5 Один вариант ответа

Что увидит пользователь, открыв адрес черновика /blog/5/?

Войдите, чтобы отмечать пройденные уроки.