Levantando um erro 404:
Vamos editar o arquivo votacao/views.py:
A View de detalhe de pergunta que é a página que mostra as questões para uma enquete lançada. Codifique:
...
from django.http import Http404
...
def detail(request, questao_id):
try:
questao = Questao.objects.get(pk=questao_id)
except Questao.DoesNotExist:
raise Http404("Questão não existe!")
return render(request, 'votacao/detail.html', {'questao': questao})
...
A view levanta uma exceção Http404 se a enquete com ID requisitado não existir.
Agora, crie o arquivo votacao/templates/votacao/detail.html.
Depois codifique:
{{ questao }}
Veja o resultado de 2 testes, exibindo a questão (/votacao/2/, e outro exibindo o erro levantado (/votacao/3/):
É comum usar get() e levantar uma exceção Http404 se o objeto não existir. O Django fornece um atalho para isso. Veja o código de votacao/views.py:
from django.shortcuts import get_object_or_404
...
def detail(request, questao_id):
questao = get_object_or_404(Questao, pk=questao_id)
return render(request, 'votacao/detail.html', {'questao': questao})
...
A função get_object_or_404() recebe um model do Django como 1º argumento e um número arbitrário de argumentos chave, que ele passa para a função do módulo get(). E levanta uma exceção Http404 se o objeto não existir.
Porquê usamos uma função auxiliar get_object_or_404() ao invés de automaticamente capturar as exceções ObjectDoesNotExist em alto nível ou fazer a API do modelo levantar Http404 ao invés de ObjectDoesNotExist?
Porque isso seria acoplar a camada de modelo com a camada de view. Um dos principais objetivos do design do Django é manter o baixo acoplamento. Alguns acoplamentos controlados é introduzido no módulo django.shortcuts.
Existe também a função get_list_or_404(), que trabalha da mesma forma que get_object_or_404(), com a diferença de que ela usa filter() ao invés de get(). Ela levanta Http404 se a lista estiver vazia. Veja o erro apresentado na tela, com o mesmo exemplo acima:
--------------------------------------------------------------------
Melhorando a template detail.html.
Codifique:
<h1>{{ questao.texto_questao }}</h1>
<ul>
{% for escolha in questao.escolha_set.all %}
<li>{{ escolha }}</li>
{% endfor %}
</ul>
O sistema de templates usa uma sintaxe separada por pontos para acessar os atributos da variável.
No exemplo de {{ questao.texto_questao }}, 1º o Django procura por dicionário no objeto questao. Se isto falhar, ele tenta procurar por um atributo (que funciona, neste caso). Se a procura do atributo também falhar, irá tentar uma chamada do tipo list-index.
--------------------------------------------------------------------
A chamada do método acontece no laço {% for %}: o que estiver dentro deste bloco é interpretado como código Python. O questao.escolha_set.all(), retorna objetos Escolha iteráveis que são suportados para ser usado na tag {% for %}.
--------------------------------------------------------------------
Removendo URLs codificados nos templates:
Quando escrevemos o link para uma pergunta no template votacao/templates/index.html, o link foi parcialmente codificado como este:
<li><a href="/votacao/{{ questao.id }}/">
{{ questao.texto_questao }}</a></li>
O problema de se fazer desta forma é que mudar URLs em projetos com muitos templates se torna bem desafiador.
O problema de se fazer desta forma é que mudar URLs em projetos com muitos templates se torna bem desafiador.
Todavia, depois que definiu o nome do argumento na função path() em votacao/urls, você pode remover uma dependência de paths de URLs específicos definidos nas configurações de URL usando a template tag {% url %}:
<li><a href="{% url 'detail' questao.id %}">
{{ questao.texto_questao }}</a></li>
--------------------------------------------------------------------
A maneira como isso funciona é, observando as definições de URL como especificado em votacao.urls. Você pode ver exatamente onde o nome de URL 'detail' é definido a seguir:
# o valor de 'name' como chamado por {% url %} template tag:
path('<int:questao_id>/', views.detail, name='detail'),
--------------------------------------------------------------------
Se você quiser alterar a URL das views de 'detail' da enquete para outra coisa, exemplo: votacao/specifics/12/ em vez de fazê-lo nos templates, mude apenas em votacao/urls.py:
# adicionando a palavra 'specifics':
path('specifics/<int:questao_id>/', views.detail, name='detail'),
--------------------------------------------------------------------
Namespacing nomes de URL:
Este tutorial trata apenas de uma aplicação, votacao. Em projetos reais, Django, pode haver 5, 10 ou mais aplicações.
Como o Django diferencia os nomes de URL entre eles?
Por exemplo, a aplicação votacao tem uma view 'detail', mas poderíamos ter um aplicativo no mesmo projeto com este mesmo nome de view.
Como o Django sabe qual view da aplicação será criada para a url ao usar a tag de template {% url%}?
Resposta: adicionar namespaces a seu URLconf. No arquivo votacao/urls.py, adicione um app_name para configurar o namespace da aplicação. Insira o código:
...
app_name = 'votacao'
...
Em seguida, mude o template votacao/index.html:
De:
<li><a href="{% url 'detail' questao.id %}">
{{ questao.texto_questao }}</a></li>
Para:
<li><a href="{% url 'votacao:detail' questao.id %}">
{{ questao.texto_questao }}</a></li>
--------------------------------------------------------------------


Nenhum comentário:
Postar um comentário