Escrevendo Views

Uma função view, ou somente view, é simplesmente uma função Python que recebe uma requisição Web e retorna uma resposta Web. Esta resposta pode ser um conteúdo HTML de uma página, ou um redirecionamento, ou um erro 404, ou um documento XML, ou uma imagem . . . ou qualquer coisa, na verdade. O view em si contém qualquer lógica arbitrária que é necessária para retornar uma resposta. Este código pode ficar em qualquer lugar que você quiser, ao longo do seu Python path. Não há outro requerimento – sem “mágica”, por assim dizer. Por uma questão de colocar o código “em qualquer lugar”, vamos criar um arquivo chamado views.py no diretório mysite, que você criou no capítulo anterior.

Um view simples

Aqui há um view que retorna a data atual, como um documento 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)

Vamos passo-a-passo através deste código, uma linha por vez:

  • Primeiro, nós importamos a classe HttpResponse, que reside o módulo django.http, também a biblioteca datetime do Python.

  • Depois, nós definimos uma função chamada current_datetime. Esta é a função view. Cada função view recebe um objeto HttpRequest como seu primeiro parâmetro, que é tipicamente nomeado como request.

    Note que o nome da função view não importa; ele não tem de ser nomeada de uma certa forma para ser reconhecida pelo Django. Nós estamos chamando-a de current_datetime aqui, porque este nome indica claramente o que ela faz.

  • O view retorna um objeto HttpResponse que contém a resposta gerada. Cada função view é responsável por retornar um objeto HttpResponse. (Há exceções, mas serão abordadas mais tarde.)

Django's Time Zone

O Django inclui uma configuração de TIME_ZONE que por padrão é America/Chicago. Este provavelmente não é onde você mora, então você pode mudá-lo no seu arquivo settings.py.

Mapeando URLs para Views

Então, para recapitular, esta função view retorna uma página HTML, que inclui a data e hora atual. Para mostrar este view numa URL em particular, você precisará criar uma no URLconf; veja URL dispatcher para instruções.

Retornando erros

Retornar códigos de erro HTTP no Django é muito fácil. Existem subclasses do HttpResponse para um número de códigos de status comuns do HTTP além do 200 (que significa "OK"). Você pode encontrar a lista completa de subclasses disponíveis na documentação de requisição/resposta. Somente retorne um instância de uma destas subclasses ao invés de uma classe normal HttpResponse a fim de mostrar um erro. Por exemplo:

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

Não existe uma subclasse especializada para cada código resposta HTTP possível, uma vez que muitos deles não serão comuns. Porém, como documentado na documentação do HttpResponse, você também pode passar o código de status HTTP dentro de um construtor do HttpResponse para criar uma classe de retorno para qualquer código de status que você quiser. Por exemplo:

def my_view(request):
    # ...

    # Retorna um código de resposta "created" (201).
    return HttpResponse(status=201)

Como erros 404 são de longe os erros HTTP mais comuns, existe uma forma mais fácil de manipular estes erros.

A exceção Http404

Quando você retorna um erro como HttpResponseNotFound, você é responável por definir o HTML da página de erro resultante:

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

Por convenção, e porque é uma boa idéia ter uma página de erro 404 consistente para todo site, o Django provê uma exceção Http404. Se você lançar um Http404 em qualquer ponto de sua função view, o Django a pegará e retornará a página de erro padão para sua aplicação, junto com o código de erro HTTP 404. Example usage:

from django.http import Http404

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

A fim de usar a exceção Http404 para sua satisfação, você deve criar um template que será mostrado quando um erro 404 é gerado. Este template deve ser chamado 404.html e localizado no nível mais alto de sua árvore de templates.

Customizando erros de views

O view 404 (page not found)

Quando você gera uma exceção Http404, o Django carrega um view especial devotado a manipular erros 404. Por padrão, ele é o view django.views.defaults.page_not_found, que carrega e renderiza o template 404.html. Isto significa que você precisa definir um template 404.html na raiz do seu diretório de templates. Este template será usado para todos os erros 404.

Esta view page_not_found deve bastar para 99% das aplicações Web, mas se você precisa sobrescrevê-lo, você pode especificar handler404 no seu URLconf, desta forma:

handler404 = 'mysite.views.my_custom_404_view'

Por trás das cenas, o Django obriga o view 404 a procurar por handler404. Por padrão, os URLconfs contém as seguinte linha:

from django.conf.urls.defaults import *

Que se preocupa com a configuração do handler404 no módulo atual. Como você pode ver em django/conf/urls/defaults.py, handler404 é setado para 'django.views.defaults.page_not_found' por padrão. Three things to note about 404 views:

  • O view 404 é também chamado se o Django não encontrar uma combinação depois de checar todas as expressões regulares no URLconf.
  • Se você não definir se próprio view 404 -- e simplesmente usar o padrão, o que é recomendado -- você ainda tem uma obrigação: você deve criar um template 404.html na raiz do seu diretório de templates. Por padrão, o view 404 usará este template para todos os erros 404. Por padrão, o view 404 passará uma variável para o template: request_path, que é a URL que resultou no erro 404.
  • Ao view 404 é passado um RequestContext e terá acesso a variáveis fornecidas por sua configuração TEMPLATE_CONTEXT_PROCESSORS (e.g., MEDIA_URL).
  • Se DEBUG é setado como True (no seu módulo settings), então seu view 404 nunca será usado, e o traceback será mostrado no lugar dele.

O view 500 (server error)

Similarmente, o Django executa um comportamente especial no caso de um erro de execução no código do view. Se um view resulta num exceção, o Djanto irá, por padrão, chamar o view django.view.defaults.server_error, que carrega e renderiza o template 500.html.

Isto significa que você precisa definir um template 500.html na raiz do seu diretório de templates. Este template será usado para todos os erros de servidor. O view 500 padrão não passa variáveis para este template e é renderizado com um Context vazio para reduzir as chances de erros adicionais.

Este view server_error deve bastar para 99% das aplicações Web, mas se você quiser sobrescrever o view, você pode especificar handler500 no seu URLconf, desta forma:

handler500 = 'mysite.views.my_custom_error_view'

Por trás das cenas, o Django obriga o view de erro a prcurar pelo handler500. Por padrão, os URLconfs contém a seguinte linha:

from django.conf.urls.defaults import *

Que se preocupa de setar handler500 no módulo atual. Como você pode ver em django/conf/urls/defaults.py, handler500 é setado para 'django.views.defaults.server_error' por padrão.