Создание представлений

Функция представления, или коротко представление – это функция Python, которая принимает Web-запрос и возвращает Web-ответ. Ответом может быть HTML-содержимое страницы, или перенаправление, или 404 ошибка, или XML-документ, или изображение . . . что угодно. Представление содержит всю необходимую логику для создания ответа. Этот код может находиться где угодно, главное, чтобы он находился в PYTHON_PATH. Никаких других требований нет – никакой “магии”. Несмотря на возможность расположить код представлений где угодно, принято держать его в файле views.py, который находится в каталоге проекта или приложения.

Простое представление

Вот пример простого представления, которое отображает текущую дату и время, как документ HTML:

from django.http import HttpResponse
import datetime

def current_datetime(request):
    now = datetime.datetime.now()
    html = "<html><body>It is now %s.</body></html>" % now
    return HttpResponse(html)

Давайте проанализируем код строка за строкой:

  • Сначала мы импортировали класс HttpResponse из модуля django.http и библиотеку Python datetime.

  • Теперь определим функцию current_datetime. Это функция представления. Каждая функция представления принимает объект HttpRequest первым аргументом, который обычно называют request.

    Название функции может быть каким угодно, нет никаких конкретных правил для именования. Мы назвали функцию current_datetime.

  • Представление возвращает объект HttpResponse, который содержит сгенерированный ответ. Каждая функция представления должна возвращать объект HttpResponse. (Есть исключения, но мы расскажем об этом далее.)

Django’s Time Zone

Django содержит настройку TIME_ZONE равную по умолчанию America/Chicago. Возможно это не там, где вы живете, вы можете изменить эту настройку в файле настройки.

Сопоставление представления с URL

Итак, напомним, функция представления возвращает HTML-страницу, которая содержит текущую дату и время. Чтобы привязать это представление к определенному URL-у, необходимо создать URLconf; подробности смотрите в разделе Менеджер URL-ов.

Возвращение ошибок

Возвращение HTTP ошибок в Django очень просто. Существует ряд подклассов HttpResponse для распространенных HTTP-состояний, отличных от 200 (что означает “OK”). Вы можете посмотреть полный список доступных подклассов в разделе о HTTP запросах и ответах. Просто верните экземпляр необходимого подкласса вместо HttpResponse. Например:

from django.http import HttpResponse, HttpResponseNotFound

def my_view(request):
    # ...
    if foo:
        return HttpResponseNotFound('<h1>Page not found</h1>')
    else:
        return HttpResponse('<h1>Page was found</h1>')

Не существует подкласса для всех HTTP-состояний, так как многие из них редко используются. Однако, как указанно в описании HttpResponse, вы можете передать код HTTP-состояния в конструктор HttpResponse. Например:

from django.http import HttpResponse

def my_view(request):
    # ...

    # Return a "created" (201) response code.
    return HttpResponse(status=201)

Так как ошибка 404 самая используемая HTTP-ошибка, существует простой способ работы с такими ошибками.

Исключение Http404

class django.http.Http404

Если вы возвращаете ошибку HttpResponseNotFound, вы должны добавить HTML содержимое страницы с ошибкой:

return HttpResponseNotFound('<h1>Page not found</h1>')

Для удобства и чтобы все страницы для ошибки 404 выглядели одинаково, Django предоставляет исключение Http404. Если вы вызываете исключение Http404 в любой момент обработки запроса, Django перехватит его и вернет стандартную страницу 404 ошибки вашего проекта вместе с 404 кодом состояния HTTP.

Пример использования:

from django.http import Http404
from django.shortcuts import render_to_response
from polls.models import Poll

def detail(request, poll_id):
    try:
        p = Poll.objects.get(pk=poll_id)
    except Poll.DoesNotExist:
        raise Http404
    return render_to_response('polls/detail.html', {'poll': p})

Чтобы использовать Http404 исключение, вам необходимо создать шаблон для станицы с ошибкой. Этот шаблон должен называться 404.html и находиться в корневом каталоге шаблонов.

Настройка представления обрабатывающего ошибки

Представление обрабатывающее 404 ошибку(страница не найдена)

django.views.defaults.page_not_found(request, template_name='404.html')

Когда вы вызываете Http404 исключение, Django загружает специальное представление, назначение которого обрабатывать 404 ошибку. По умолчанию, это функция django.views.defaults.page_not_found(), которая возвращает сообщение “Not Found” или загружает и выполняет шаблон 404.html, если вы его создали в корне каталога с шаблонами.

Представление для обработки 404 ошибки передает в шаблон одну переменную: request_path, значение которой URL, вернувший ошибку.

Представления page_not_found хватит для 99% Web-приложений, но если вы хотите переопределить его, добавьте функцию handler404 в главный URLconf(добавление ``handler404` куда-либо еще не сработает), например:

handler404 = 'mysite.views.my_custom_404_view'

При 404 ошибке Django ищет функцию handler404 в URLconf, если она не найден - использует django.views.defaults.page_not_found.

Три вещи, которые необходимо знать о представлении, обрабатывающем 404 ошибку:

  • 404-представление вызывается, если Django не находит подходящего URL-шаблона в URLconf.

  • Представление обрабатывающее 404 ошибку использует RequestContext, и в шаблоне будут доступные все переменные, добавленные процессорами контекста из настройки TEMPLATE_CONTEXT_PROCESSORS (например, MEDIA_URL).

  • Если DEBUG установлен в True (в настройках проекта), представление для обработки 404 ошибки никогда не будет использовано, и будет показан URLconf с отладочной информацией.

Представление обрабатывающее 500 ошибку(ошибка сервера)

django.views.defaults.server_error(request, template_name='500.html')

Кроме того, Django вызывает определенный обработчик и при исключении в коде. Если представление вызовет исключение, Django по умолчанию вызовет представление django.views.defaults.server_error, которое вернет сообщение “Server Error” или загрузит и вернет шаблон 500.html, если такой существует.

Представление обрабатывающее ошибку 500 не передает переменных в шаблон и использует Context, чтобы избежать дополнительных ошибок.

Представления server_error хватит для 99% Web-приложений, но если вы хотите переопределить его, добавьте функцию handler500 в URLconf, например:

handler500 = 'mysite.views.my_custom_error_view'

При 500 ошибке Django ищет функцию handler500 в URLconf, если она не найден - использует django.views.defaults.server_error.

Одна вещь необходимо знать о представлении обрабатывающем 500 ошибку:

  • Если DEBUG установлен в True (в настройках проекта), представление для обработки 500 ошибки никогда не будет использовано, и будет показан стек вызовов с отладочной информацией.

Представление обрабатывающее 403 ошибку(запрещено)

django.views.defaults.permission_denied(request, template_name='403.html')

Как и для 404 и 500 ошибок, Django вызывает представление для обработки 403 ошибки. Если представление вызовет 403 исключение, Django по умолчанию выполнит представление django.views.defaults.permission_denied.

Это представление загружает и выполняет шаблон 403.html из корневом каталоге шаблонов, или, если он не существует, вернет текст “403 Forbidden”, в соответствии с RFC 2616 (спецификация HTTP 1.1).

django.views.defaults.permission_denied вызывается при исключении PermissionDenied. Ограничить доступ вы можете следующим образом:

from django.core.exceptions import PermissionDenied

def edit(request, pk):
    if not request.user.is_staff:
        raise PermissionDenied
    # ...

Как и для 404 и 500 ошибок, вы можете переопределить django.views.defaults.permission_denied указав функцию handler403 в главном URLconf:

handler403 = 'mysite.views.my_custom_permission_denied_view'

Представление обрабатывающее 400 ошибку(неверный запрос)

New in Django 1.6.
django.views.defaults.bad_request(request, template_name='400.html')

Если Django взывает исключение SuspiciousOperation, оно может быть обработано другими компонентами (например, будет сброшены данные сессии). Если исключение не обработано, Django пометит запрос как неверный(‘bad request’) вместо вызова ошибки сервера.

django.views.defaults.bad_request очень похоже на представление server_error, но возвращает 400 ответ, означающий, что ошибка вызвана на стороне клиента.

Как и server_error, стандартного bad_request хватит для 99% Web-приложений, но если вы хотите переопределить его, добавьте функцию handler400 в главный URLconf, например:

handler400 = 'mysite.views.my_custom_bad_request_view'

bad_request используется только при DEBUG равном False.