En django existen dos formas de crear un formulario, una es crear cada campo manualmente y la otra es crearlos automáticamente basados en el modelo de datos.
Ya que casi siempre los formulario se usan para agregar/editar una tabla en una BD, y los campos del formulario reflejan los campos de la tabla, seria un desperdicio de tiempo crearlos manualmente.
Dejemos de hablar y empecemos a escribir código, editemos el archivo forms.py en el directorio de nuestra aplicación:
from django.forms import ModelForm #1 from blog.models import Comment #2 class CommentForm(ModelForm): #3 """Formulario de comentarios""" class Meta: #4 model = Comment #5 exclude = ("post","deleted") #6
Hora de explicar lo que hemos hecho:
- Importamos ModelForm, la base para los formularios basados en modelos de datos.
- Importamos el modelo para el que se creará el formulario
- Creamos una subclase de ModelForm.
- En la clase Meta especificamos como crear el formulario
- model: modelo en el que se basa el formulario.
- exclude: campos a excluir, en este ejemplo post lo asignamos según el articulo desde el que se envió el comentario y deleted lo decidimos en la pagina de administración si es un comentario insultante. Si son muchos los campos a excluir podemos hacer lo contrario y especificar los que se deben incluir.
# Archivo views.py from blog.models import Post, Tag, Comment from blog.forms import CommentForm ... # la función recibe el numero capturado def single(request, id=0): # recuperar post según id post = Post.objects.get(id=int(id)) # Crear formulario form = CommentForm() return render_to_response("single.html", locals())Para crear el formulario se instancia el objeto adecuado y en la vista se usa esta instancia para mostrar el formulario:
{# plantilla single.html #} {% extends 'base.html' %} {% block main_content %} {% include 'include/article.html' %} {# necesitamos crear el tag form #} <form action="" method="form"> {{ form }} </form> {% endblock %}Con esto veremos el formulario en nuestro blog, lo llenamos y enviamos...
# Archivo views.py from blog.models import Post, Tag, Comment from blog.forms import CommentForm # importamos el decorador from django.views.decorators.csrf import csrf_protect # importamos render from django.shortcuts import render ... # aplicamos el decorador función que recibe datos de formulario @csrf_protect def single(request, id=0): # recuperar post según id post = Post.objects.get(id=int(id)) form = CommentForm() # usamos render en lugar de render_to_response return render(request, "single.html", locals())Ahora incluimos el tag
{% csrf_token %}
dentro del formulario en la plantilla single.html. Esto crea un elemento input oculto con un token único que se verifica al enviar datos al servidor, si este no coincide, se produce un error 403 (prohibido) y tenemos una app algo mas segura.Ok, ya podemos enviar datos del formulario al servidor, hora debemos validarlos y guardarlos en la BD.
# Archivo views.py @csrf_protect def single(request, id=0): # recuperar post según id post = Post.objects.get(id=int(id)) # recuperar comentarios de este post comments = Comment.objects.filter(post=post) # Si la petición es POST es porque enviaron el formulario if request.method == "POST": # Creamos una instancia del modelo Comment asignado el post actual comment = Comment(post=post) # Creamos una instancia del formulario con los datos recibidos form = CommentForm(request.POST, instance=comment) # Validamos los datos if form.is_valid(): # Guardamos el comentario en la BD form.save() # Enviamos al usuario de nuevo al post return HttpResponseRedirect("/post/{0}".format(slug)) # De lo contrario creamos un formulario vacío else: form = CommentForm() return render(request, "single.html", locals())Podemos notar algunas cosas:
- Validamos el formulario con el método is_valid que no definimos. ¿como es esto posible?; Al crear el modelo Comment especificamos el tipo de datos admitidos, el formulario "sabe" que si esto datos no corresponden, el formulario contiene errores.
- Para guardar los datos usamos form.save y no comment.save. Esto se debe a que hay datos que no están incluidos en el formulario (post) pero si en la instancia comment y viceversa, por esto pasamos comment al formulario en el momento de crearlo.
{# plantilla single.html #} {% extends 'base.html' %} {% block main_content %} {% include 'include/article.html' %} {% for comment in comments %} <div class="comment"> <div class="user">{{ comment.name }} dijo:</div> <div class="body">{{ comment.body }}</div> <small>{{ comment.date|date:"d-m-Y" }}</small> </div> {% endfor %} {# necesitamos crear el tag form #} <form action="" method="form"> {{ form }} </form> {% endblock %}Con esto solo falta crear el sitio de administración para agregar post y moderar los comentarios y tendremos un blog terminado. Estén pendientes por la ultima parte de esta serie que seguro saldrá antes que se acabe el mundo este 21 de diciembre XD.
7 Responses to “Creando un blog con django - parte 4”
Hola, que tal? He seguido tu tutorial, muy completo, espero coloques pronto las proximas partes. Lo estoy probando bajo win7 con python 2.7 y django 1.4, pero al momento de probarlo me lanza este error:
ImportError at /
No module named shorcuts
Me baje e instale este paquete de aquí --> https://github.com/jgorset/django-shortcuts
Y sin embargo sigue el mismo error, que podrá ser?
Espero puedas ayudarme. Saludos =)
hola que pena la demora.
He encontrado varias "soluciones" pero en estos momentos no cuento con una maquina con windows instalado, así que no puedo probar ninguna.
Cuando haya confirmado que alguna de estas sirve te aviso.
Muy buen tutorial, aunque te faltaron unos puntos que dan error; por ejemplo:
En la vista falto importar
from django.http import HttpResponse, HttpResponseRedirect
Y esta linea
return HttpResponseRedirect("/post/{0}".format(slug))
Debe ser así
return HttpResponseRedirect("/post/{0}")
muchas gracias, si se me olvido importar HttpResponseRedirect :(.
pero en la linea
return HttpResponseRedirect("/post/{0}".format(slug))
si debe ir así ya que el format reemplaza {0} por el slug del post, si no se hace esto se redirecciona a /post/{0} que es una pagina que no existe.
Excelente Gracias, lo estaba buscando...
Excelente! espero la parte final XD
Excelente tutorial viejo ...espero con ansias la ultima parte ... :D
Deja una respuesta