Aula 14 - Curso de Django
Criando uma primeira aplicação com Django e mysql
Criação da interface pública – "views".
Visão Geral
- Uma view é um “tipo” de página Web da sua aplicação Django, que em geral serve a uma função específica e tem um template específico. Por exemplo, em uma aplicação de blog, você deve ter as seguintes views:
- Página inicial do blog - exibe os artigos mais recentes.
- Página de “detalhes” - página de vínculo estático, a página do artigo em si.
- Página de arquivo por ano - exibe todos os artigos de todos os meses em determinado ano.
- Página de arquivo por mês - exibe todos os artigos por dia em determinado mês.
- Página de arquivo por dia - exibe todos os artigos de um determinado dia.
- Ação de comentários - controla o envio de comentários para um artigo.
Em nossa aplicação de enquetes, nós teremos as seguintes views:
- Página de “índice” de enquetes - exibe as enquetes mais recente.
- Página de “detalhes” da Question – exibe o texto da questão, sem resultados, mas com um formulário para votar
- Página de “resultados” de perguntas - exibe os resultados de uma pergunta em particular.
- Ação de voto - gerencia a votação para uma escolha em uma enquete específica.
No Django, páginas web e outros conteúdos são entregues por views.
Cada view é representada por uma simples função Python(ou metodos, no caso das views baseadas em classes).
O django irá escolher uma view examinando a URL que foi requisitada (para ser preciso, a parte da URL depois do nome de domínio).
Você já deve ter visto urls na internet desse tipo:
“ME2/Sites/dirmod.aspsid=&type=gen&mod=Core+Pages&gid=A6CD4967199A42D9B65B1B”.
Você ficará satisfeito em saber que o Django permite padrões de URL muito mais elegantes do que isso.
Um padrão de URL é simplesmente a formatação geral de uma URL - por exemplo: /newsarchive/<year>/<month>/.
Para ir de uma URL para uma view, O Django usa o que é conhecido como ‘URLconfs’.
Uma URLconf mapeia padrões de URL (descritas com expressões regulares) para views.
Antes de escrever as views, modifique o mysite/urls para que fique assim:
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('polls/', include('polls.urls')),
path('admin/', admin.site.urls)
]
Veja que incluímos o urls da pasta polls aqui no urls da pasta mysite.
Agora vamos adicionar algumas
views em
polls/views.py.
Crie então o polls/views.py
A view
index() mostra as últimas 5 “
poll questions” do sistema, separada por vírgulas, de acordo com sua data de publicação.
polls/views.py
from django.http import HttpResponse
from .models import Question
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
output = ', '.join([q.question_text for q in latest_question_list])
return HttpResponse(output)
def detail(request, question_id):
return HttpResponse("You're looking at question %s." % question_id)
def results(request, question_id):
response = "You're looking at the results of question %s."
return HttpResponse(response % question_id)
def vote(request, question_id):
return HttpResponse("You're voting on question %s." % question_id)
Ligue as
views dentro do módulo
polls.urls adicionando as seguintes chamadas:
polls/urls.py
from django.urls import path
from . import views
urlpatterns = [
# ex: /polls/
path('', views.index, name='index'),
# ex: /polls/5/
path('/', views.detail, name='detail'),
# ex: /polls/5/results/
path('/results/', views.results, name='results'),
# ex: /polls/5/vote/
path('/vote/', views.vote, name='vote'),
]
- /polls/34/ executa o método detail() e mostra o ID que você informou na URL.
- “/polls/34/results/” e “/polls/34/vote/” – vai mostrar a pagina resultados e a pagina de votação.
Obs. Se preferir a implementação antiga usando url() com regex ao invés de path() coloque no /polls/urls.py o conteúdo abaixo:
from django.conf.urls import url
from . import views
urlpatterns = [
# ex: /polls/
url(r'^$', views.index, name='index'),
# ex: /polls/5/
url(r'^(?P[0-9]+)/$', views.detail, name='detail'),
# ex: /polls/5/results/
url(r'^(?P[0-9]+)/results/$', views.results, name='results'),
# ex: /polls/5/vote/
url(r'^(?P[0-9]+)/vote/$', views.vote, name='vote'),
]
A nova funçao django.urls.path() permite uma sintaxe de roteamento de URL mais simples e mais legível. Por exemplo, nas versões anteriores do Django:
url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
pode agora ser escrito como:
path('articles/<int:year>/', views.year_archive),
Com a função
url(), quando alguém requisita uma página do seu site – vamos dizer, "/polls/34", o Django irá carregar o módulo Python mysite.urls porque este está sendo apontado pela definição ROOT_URLCONF.
Ele encontra a variável denominada urlpatterns e atravessa as expressões regulares seguindo a ordem.
Depois de encontrar uma combinação no '^polls/', ele corta o texto que combina ("polls/") e envia a parte remanescente – "34/" – para o URLconf do 'polls.urls' para processamento posterior.
Lá ele encontra a r'^(?P<question_id>[0-9]+)/$', resultando em uma chamada para a "view" detail() como esta:
detail(request=<HttpRequest object>, question_id='34')
A parte question_id='34' vem de
(?P<question_id>[0-9]+).
Usando parênteses em torno de um padrão "captura-se" o texto que casa com esse padrão e envia ele como um argumento da função;
?P<question_id> define o nome que será usado para identificar o padrão casado;
[0-9]+ é a expressão regular para casar uma sequência de dígitos (ex., um número)
Como os padrões de URL são expressões regulares, realmente não há limites para o que você possa fazer com elas. E também não é necessário adicionar extensão na URL como .html - a menos que você queira, neste caso você pode fazer algo como:
url(r'^polls/latest\.html$', views.index),
Mas não faça isso, isto não é funcional.
Quando o vídeo dessa aula foi gravado, a jeito como se fazia o roteamento de urls era usando url().
Agora, pela documentação oficial, é melhor e mais simples usar a funcão path() ao invés de url().
Escreva views que façam algo
Cada view é responsável por fazer uma de duas coisas: retornar um objeto HttpResponse contendo o conteúdo para a página requisitada, ou levantar uma exceção como Http404.
Sua view pode ler registros do banco de dados, ou não.
Ela pode usar um sistema de templates como o do Django - ou outro sistema de templates Python de terceiros - ou não.
Pode gerar um arquivo PDF, uma saída em XML, criar um arquivo ZIP sob demanda, qualquer coisa que você quiser, usando qualquer biblioteca Python que você queira.
Tudo que o Django espera é que a
view retorne um
HttpResponse, ou uma
exceção.
Por ser mais conveniente, vamos usar a própria API de banco de dados do Django, a qual vimos na parte 2 do Tutorial.
Há um problema aqui, o design da página esta codificado na view. Se você quiser mudar a forma de apresentação de sua página, você terá de editar este código diretamente em Python. Então, vamos usar o sistema de templates do Django para separar o design do código Python:
Primeiro, crie um diretório chamado templates em seu diretório polls.
O Django irá procurar por templates lá.
A sua configuração de projeto TEMPLATES descreve como o Django vai carregar e renderizar templates.
O arquivo de configuração padrão usa o backend DjangoTemplates do qual a opção APP_DIRS é configurada como True. Por convenção DjangoTemplates procura por um subdiretório “templates” em cada uma das INSTALLED_APPS.
Dentro do diretório templates que acabou de criar, crie outro diretório polls, e dentro crie um arquivo chamado index.html. Em outras palavras, seu template deve estar em polls/templates/polls/index.html. Devido a forma como o carregador de templates app_directories funciona como descrito acima, você pode referenciar este template dentro do Django simplesmente como polls/index.html.
Namespacing de template
Agora nós podemos ser capazes de avançar com a colocação dos nossos modelos diretamente em polls/templates (em vez de criar outro subdiretório poll), que na verdade seria uma má ideia.
Django irá escolher o primeiro template que encontra cujo nome corresponde, se você tivesse um template com o mesmo nome em uma aplicação diferente, o Django seria incapaz de distinguir entre eles, por isso, precisamos apontar o Django no caminho certo, e a maneira mais fácil de fazer isso é usar namespacing, ou seja, colocar esses templates dentro de outro diretório nomeado para a aplicação em si.
Ponha o seguinte código neste template:
polls/templates/polls/index.html
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li><a href="/polls/{{ question.id }}/">{{ question.question_text }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available.</p>
{% endif %}
Agora vamos atualizar nossa view index em polls/views.py para usar o template:
polls/views.py
from django.http import HttpResponse
from django.template import loader
from .models import Question
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
template = loader.get_template('polls/index.html')
context = {
'latest_question_list': latest_question_list,
}
return HttpResponse(template.render(context, request))
Esse código carrega o template chamado polls/index.html e passa um contexto para ele. O contexto é um dicionário mapeando nomes de variáveis para objetos Python.
Carregue a página apontando seu navegador para “/polls/”, e você deve ver uma lista contendo a questão “What’s up” do Tutorial 2. O link aponta para página de detalhes das perguntas.
Um atalho: render()
É um estilo muito comum carregar um template, preenchê-lo com um contexto e retornar um objeto HttpResponse com o resultado do template renderizado. O Django fornece este atalho. Aqui esta toda a view index() reescrita:
polls/views.py
from django.shortcuts import render
from .models import Question
def index(request):
latest_question_list = Question.objects.order_by('-pub_date')[:5]
context = {'latest_question_list': latest_question_list}
return render(request, 'polls/index.html', context)
Note que uma vez que você tenha feito isto em todas as views, nós não vamos mais precisar importar loader e HttpResponse (você vai querer manter HttpResponse se você ainda tiver os métodos criados para detail, results e vote).
A função render() recebe o nome do template como primeiro argumento e um dicionário opcional como segundo argumento. Ele retorna um objeto HttpResponse do template informado renderizado com o contexto determinado.
Obrigado
Até a próxima