Представления (Views)

Представления (Views)

Представления (views), или как их ещё называют "джангисты", "вьюхи" — центральные персонажи Web-приложений на основе Django. Ваше приложение может не взаимодействовать с базой данных, может не использовать шаблоны, но views в нём будут обязательно — приложение ведь должно как-то отвечать на запросы! :)

В Django используются два вида представлений:

  1. Представления-функции (view functions),
  2. Представления-классы (class based views).

В одном проекте могут одновременно использоваться оба вида. И нельзя сказать, что какой-то один вид лучше другого по всем признакам — у обоих видов есть свои сильные и слабые стороны.

Представления-функции

Рассмотрим сначала более простой (но не менее мощный) вид - обычные функции, принимающие на входе запрос (объект класса HttpRequest) и возвращающие ответ (объект класса HttpResponse или ему подобных).

Так как каждая view function получает полную информацию о запросе, ей одной решать, как этот запрос обрабатывать. Так, например, функция решает, как реагировать на методы HTTP и как обрабатывать параметры запроса:

def login(request):
    if request.method == 'GET':
        return render(request, 'login_page.html', context={
            'username': request.GET['username']
        })
    elif request.method == 'POST':
        username = request.POST['username']
        password = request.POST['password']
        check_password(username, password)
        ...

И раз представление — это обычная функция, к ней можно применять обычные же декораторы! В Django есть несколько полезных. Вот один из них:

from django.views.decorators.http import require_http_methods

@require_http_methods(['GET', 'POST'])
def login(request):
    ...

Если такая view получит запрос с отличным от указанных методом, то автоматически будет сформирован ответ ResponseNotAllowed (код 405).

View function очень просты концептуально и дают вам полный контроль над обработкой запроса. Это, безусловно полезно, но заставляет каждый раз писать код вручную. Или подготавливать библиотечку декораторов, упрощающих решение типичных задач.

Представления-классы

Все представления этого вида наследуются от класса django.views.View. Так выглядит код в простейшем случае:

from django.http import HttpResponse
from django.views import View

class IndexView(View):

    def get(self, request, *args, **kwargs):
        return HttpResponse('Hello, World!')

Метод get здесь работает точь-в-точь как view function. При этом на каждый запрос будет создан новый экземпляр этого класса, так что вы смело можете объявлять в классе методы, которые по ходу выполнения запроса будут менять его состояние.

Регистрируется представление-класс с помощью метода (метода класса) as_view. Выглядит регистрация так:

urlpatterns = [
    ...
    path('', IndexView.as_view()),
    ...

Чем же представления-классы хороши? Возможностью лёгкого переиспользования поведения через наследование. Взглянем на встроенный TemplateView из модуля django.views.generic.base в деле:

urlpatterns = [
    ...
    path('', TemplateView.as_view(template_name='index.html')),
    ...

Нам даже не пришлось наследовать класс, мы просто использовали готовый, указав при регистрации имя шаблона!

Но даже если бы мы унаследовали класс, чтобы передать шаблону какие-то данные (в контексте), то нам бы пришлось переопределить лишь малую часть функциональности класса-предка:

from django.views.generic.base import TemplateView

class HomePageView(TemplateView):

    template_name = "home.html"

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['who'] = 'World'
        return context

И подобных базовых представлений (base views) Django содержит предостаточно! Особенно хорошо проработаны представления для отображения сущностей из базы данных: здесь вам и отображение списков записей, и отображение отдельных записей в детализированной форме. Сказывается направленность Django на решение задач по разработке контентных сайтов.

Представления-классы хорошо подходят для решения повторяющихся задач. Большая часть из которых, к тому же, уже "почти решена" силами Django.

Задание для самостоятельной работы

В нашем проекте hello_django

  • переделайте hello_django.views.index c использованием TemplateView (вам понадобится наследование),
  • переделайте hello_django.calc.view в класс-потомок от View (в дальнейшем мы будем расширять этот класс).
Мы учим программированию с нуля до стажировки и работы. Попробуйте наш бесплатный курс «Введение в программирование» или полные программы обучения по Javascript, PHP, Python и Java.

Хекслет

Подробнее о том, почему наше обучение работает →