Utilizamos cookies propias y de terceros para hacer funcionar y mejorar nuestros servicios. Si continúa navegando, consideramos que acepta su uso. Puede obtener más información visitando nuestra política de cookies.
DJANGO - CONSTUIR UNA VISTA CON FORMULARIO
En esta sesión demostramos la construcción de una vista con un formulario sencillo, definido desde la propia plantilla de Django, y cómo procesar el envío de los datos usando el patrón redirect-after-post.
Cargando video...
NOTA: Solo puedes ver una versión limitada del video a baja resolución, si quieres ver la versión completa por favor regístrate y obtén alguno de nuestros planes!
Descripción del Vídeo
Construiremos un formulario sencillo para registrar un "voto" en una pregunta y la acción (vista) que procese su envío, teniendo en cuenta:
La construcción adecuada de la URL a la que se envía el formulario
El token para prevenir ataques Cross-Site Request Forgeries (CSRF)
Validaciones sencillas en la lógica de la vista
Posibles casos de fallas por concurrencia
El patrón redirect-after-post: hacer una redirección HTTP (en este caso, a la página de resultados) luego de enviar el formulario para evitar la doble acción al navegar "Atrás".
Código disponible en:
https://github.com/networkfaculty/Fundamentos-Django/releases/tag/d-2.3.4
curso/encuestas/views.py
from django.shortcuts import get_object_or_404, render
from django.http import HttpResponse
from .models import Pregunta, Opcion
from django.http import Http404, HttpResponseRedirect
from django.db.models import F
from django.core.urlresolvers import reverse
def index(request):
preguntas_recientes = Pregunta.objects.order_by('-fe_publicacion')[:5]
context = {'preguntas_recientes': preguntas_recientes,
'titulo': 'Listado de Encuestas' }
return render(request, 'encuestas/index.html', context)
def detalle(request, id_pregunta):
pregunta = get_object_or_404( Pregunta, pk=id_pregunta )
return render(request, 'encuestas/detalle.html', {'pregunta': pregunta})
def votar(request, id_pregunta):
pregunta = get_object_or_404( Pregunta, pk=id_pregunta )
try:
# Nos aseguramos de que el código de la opción recibida esté dentro de las
# opciones registradas para la pregunta
opcion_seleccionada = pregunta.opcion_set.get(pk=request.POST['opcion'])
# Incrementamos la cantidad de votos para la opción seleccionada, pero desde la
# base de datos directamente
# opcion_seleccionada.votos += 1 # Esto puede generar problemas en transacciones
# concurrentes
opcion_seleccionada.votos = F('votos') + 1
opcion_seleccionada.save()
# Nota: Lo anterior también podría escribirse de forma compacta como:
# opcion_seleccionada.update( votos = F('votos') + 1 )
# Luego de guardar exitosamente, redireccionamos a página de resultados.
# Utilizamos 'reverse' para obtener de manera reutilizable la URL de la vista a
# la que queremos redirigir al usuario.
return HttpResponseRedirect(reverse('encuestas:resultados',
kwargs={'id_pregunta': pregunta.id}))
except (KeyError, Opcion.DoesNotExist):
# En caso de un código incorrecto o faltante de opción, volver a mostrar el formulario
return render(request, 'encuestas/detalle.html', {
'pregunta': pregunta,
'mensaje_error': "Opción faltante o inválida",
})
def resultados(request, id_pregunta):
pregunta = get_object_or_404( Pregunta, pk=id_pregunta )
return render(request, 'encuestas/resultados.html', {'pregunta': pregunta})
-curso/encuestas/urls.py
from django.conf.urls import url
from . import views
urlpatterns = [
# ej: /encuestas/
url(r'^$', views.index, name='index'),
# ej: /encuestas/5
url(r'^(?P\d+)/$', views.detalle, name='detalle'),
# ej: /encuestas/5/resultados
url(r'^(?P\d+)/resultados$', views.resultados, name='resultados'),
# ej: /encuestas/5/votar
url(r'^(?P\d+)/votar$', views.votar, name='votar'),
]
curso/encuestas/templates/encuestas/detalle.html
{% extends 'encuestas/base.html' %}
{% block encabezado %}
Detalle de Encuesta: {{ pregunta.texto_pregunta|truncatewords:5|escape }}...
{% endblock encabezado %}
{% block contenido %}
{% if mensaje_error %}{{ mensaje_error }}
{% endif %}
{{ pregunta.texto_pregunta|escape }}
Ver resultados
{% endblock contenido %}
-curso/encuestas/templates/encuestas/resultados.html
{% extends 'encuestas/base.html' %}
{% block encabezado %}
Resultados de Encuesta: {{ pregunta.texto_pregunta|truncatewords:5|escape }}...
{% endblock encabezado %}
{% block contenido %}
{{ pregunta.texto_pregunta|escape }}
{% for opcion in pregunta.opcion_set.all %}
- {{ opcion.texto_opcion }} -- {{ opcion.votos }} voto(s)
{% endfor %}
Votar
{% endblock contenido %}
Rating
Global
comments powered by Disqus