Blog
Hablemos de los formularios en Django
- Publicado por: Rafael Fernandez
- Categoría: Curso Desarrollo Web Django

-En esta parte hablaremos sobre los formularios en Django, como utilizarlos, editarlos, validarlos e implementarlos.
-Citaremos códigos de ejemplo de implementación.
Para finalizar y darle el toque necesario a la página web, es necesario elaborar una sección con la finalidad de añadir y editar artículos (post) dentro del blog. Django admin está perfecto, pero es realmente complicado en cuanto a su personalización y que quede con buen aspecto. Utilizando forms se tendrá la posibilidad de gestionar completamente la interfaz (se podrá hacer casi todo tipo de acciones). Lo mejor de esto es que Django gorms es el elemento ideal para definir cada aspecto desde cero o haciendo un ModelForm que se archivará en el resultado de cada formulario de su modelo.
Eso es verdaderamente lo que se pretende ejecutar: hacer un formulario para el modelo de Post.
Como todo importa en estos temas de Django, forms carga con su propio archivo denominado: forms.py.
Habrá que crear un archivo con dicho nombre en el directorio de blog.
blog └── forms.py
Bien, lo que sigue a continuación es abrirlo para tipear el código siguiente:
</pre> from django import forms from .models import Post class PostForm(forms.ModelForm): class Meta: model = Post fields = ('title', 'text',) <pre>
Principalmente se necesitará la importación Django forms (from django import forms) y, es obvio, el modelo Post (from .models import Post). PostForm, sería el nombre designado de dicho formulario. Se necesita decirle a Django que dicho formulario es un ModelForm (por lo que Django se encargará de hacer todo por el usuario) – forms.ModelForm es quien se encarga de eso.
Lo que sigue ahora es que usar class Meta, en el sitio que sugerimos en Django, es decir, el modelo que se tiene que utilizar para poder elaborar el formulario (model = Post).
Para terminar, se pueden comentar los campos (s) que se desean en el formulario. En ese sentido, solo se necesitará de title y text – author que será el sujeto encargado en autenticarse y donde created_date se leerá de forma automática al momento de crear un artículo (post) o sea, dentro del código ¿Vale?
Y con ello se finaliza, ya está todo lo que se requiere a ejecutar y únicamente se debe utilizar el formulario en una view para exhibirla en la plantilla.
Cuando se pretenda elaborar: un link en el sitio, la URL, alguna vista y la plantilla.
Link a un sitio utilizando el formulario
Es momento de abrir blog/templates/blog/base.html. Se deberá agregar un link en div designado page-header:
<a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a>
Tener en cuenta que se desea llamar a la nueva vista post_new. Luego de añadir la línea, el archivo HTML tendría que cargar el siguiente semblante:
{ {% load staticfiles %} <html> <head> <title>Django blog</title> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css"> <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap-theme.min.css"> <link href='//fonts.googleapis.com/css?family=Lobster&subset=latin,latin-ext' rel='stylesheet' type='text/css'> <link rel="stylesheet" href="{% static 'css/blog.css' %}"> </head> <body> <div class="page-header"> <a href="{% url 'post_new' %}" class="top-menu"><span class="glyphicon glyphicon-plus"></span></a> <h1><a href="/">Django Girls Blog</a></h1> </div> <div class="content container"> <div class="row"> <div class="col-md-8"> {% block content %} {% endblock %} </div> </div> </div> </body> </html>
Después de ello solo habrá que guardarlo y actualizar el sitio de http://127.0.0.1:8000 y aparecerá un error NoReverseMatch el cual es familiar, ¿no?
URL
Para esto debe abrirse el blog/urls.py y anexar la siguiente línea:
url(r'^post/new/$', views.post_new, name='post_new'),
En cuanto al código, debería tener el siguiente aspecto:
</pre> from django.conf.urls import url from . import views urlpatterns = [ url(r'^$', views.post_list), url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail), url(r'^post/new/$', views.post_new, name='post_new'), ] <pre>
Luego de ello, solo queda actualizar la página, se verá como AttributeError, ya que no existe la vista de post_new todavía. Ahora mismo se implementará.
Vista post_new
Ahora mismo habrá que abrir el archivo blog/views.py y anexar las líneas siguientes en las filas from:
from .forms import PostForm
Ahora agregar la vista:
def post_new(request): form = PostForm() return render(request, 'blog/post_edit.html', {'form': form})
Si quieres elaborar un nuevo formulario Post, es necesario llamar a PostForm( ) y enviarlo a la plantilla correspondiente. Se volverá a la vista pero, ahora mismo, se creará de manera rápida con una plantilla para el formulario.
Plantilla
Se debe hacer un nuevo archivo post_edit.html donde el directorio sería blog/templates/blog. Todo para lograr que el formulario trabaje. Se requiere de algunas cosas para ello:
- Habrá que exhibir el formulario. Se puede hacer, por ejemplo, utilizando el ya conocido {{ form.as_p }}.
- En cuanto a la línea mostrada anteriormente, debe estar encerrada en una etiqueta de formulario HTML: <form method=”POST”>…</form>
- Asimismo, se requiere de un botón de “Guardar”. Para hacerlo en HTML se usa el código: <button type=’submit’>Save</button>
- Y, para terminar, luego de la apertura de <form…> se requiere anexar {% csrf_token %}. Este paso es relevante debido a que hará que cada formulario sea seguro. Djando estará quejándose en caso de que se olvide anexar el código.
Ahora se verá de qué manera estará el HTML en el post_edit.html:
</pre> {% extends 'blog/base.html' %} {% block content %} <h1>New post</h1> <form method="POST" class="post-form">{% csrf_token %} {{ form.as_p }} <button type="submit" class="save btn btn-default">Save</button> </form> {% endblock %} <pre>
Es momento de actualizar la página y ver el formulario.
Sin embargo, no todo está completado. Es porque si se escribe algo dentro del campo de títle y text y se intenta guardar cada cambio no sucederá nada. Otra vez se regresa al mismo sitio y el texto desapareció, es decir que ningún artículo (post) nuevo ha sido incluido. ¿Qué hacer?
Nada, hacer absolutamente nada ya que se debe trabajar más es en la vista.
Guardar el formulario
def post_new(request): form = PostForm() return render(request, 'blog/post_edit.html', {'form': form})
En el instante que se envié el formulario, se estará nuevamente en la misma vista, pero ahora existen variedad de información anexos en request, concretamente en request.POST (dicho nombre no tiene relación alguna con los artículos (posts) del blog, hace alusión a lo que se está “publicando” por su traducción al inglés, posting- datos).
Hay que recordar un poco sobre el archivo HTML donde la definición de <form> poseía la cambiante de method=”POST”. Es allí donde cada campo del formulario permanece actualmente en request.POST. No hay por qué cambiar el nombre de la variable POST (ya que es el nombre que de igual forma es válido para la variable de method es GET, sin embargo, ya habrá tiempo suficiente para saber las discrepancias).
En la view hay dos opciones de contexto a observar. El principal es que al momento de acceder al sitio web por vez primera y se desee un formulario en blanco. La otra es cuando se regresa a la view con la información del formulario que se acaba de escribir. Así que se debe añadir la condición y para eso se usará if.
if request.method == "POST": [...] else: form = PostForm()
Ahora es momento de llenar cada punto […]. Es ese method haciendo alusión POST lo que se pretende crear usando PostForm con cada dato del formulario y se hará con el siguiente código:
form = PostForm(request.POST)
Lo que sigue a continuación es corroborar si dicho formulario está correcto (cada uno de los campos necesitados están definidos y no existe un valor erróneo). Se hace con form.is_valid().
Se corroborará que dicho formulario sea válido, y así fue, se puede salvar.
if form.is_valid(): post = form.save(commit=False) post.author = request.user post.save()
Es decir que por encima existen dos cosas a considerar: Una es guardar el formulario con form.save y agregar el autor (debido a que no existía ningún campo de autor dentro del PostForm y dicho campo es necesario). commit=False se refiere a que no se desea guardar el modelo Post aún (ya que primero se debe agregar el autor). Muchas veces se usará form.save(), sin commit=False, pero en ese sentido, hay que ejecutarlo. post.save() se encargará de mantener cada ajuste (agregando el autor) y se elaborara un nuevo artículo (post) dentro del blog.
Para finalizar, sería conveniente si se pudiese ir al sitio de post_detail donde está el artículo (post) nuevo del blog, ¿verdad? Para lograr ello, hay que importar lo siguiente:
from django.shortcuts import redirect
Hay que añadirlo al comienzo de dicho archivo. Y ahora se puede hacer lo siguiente: Ir al sitio post_detail donde está el artículo (post) recién hecho.
En caso de que el paso falle y salga “NoReverseMatch” es porque la url no se nombró.
Al ver el archivo blog/urls.py se modifica lo siguiente:
url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail)
Por
url(r'^post/(?P<pk>[0-9]+)/$', views.post_detail, name='post_detail')
post_detail sería el nombre designado a la vista que se quiere ir. Recordar que dicha view necesita de la variable pk. Por ello, hay que enviarlo a la vista haciendo empleo del pk=post.pk, donde post es el artículo (post) que se ha hecho.
Ahora bien, lo que pretenderemos será observar cómo está la vista actualmente.
def post_new(request): if request.method == "POST": form = PostForm(request.POST) if form.is_valid(): post = form.save(commit=False) post.author = request.user post.published_date = timezone.now() post.save() return redirect('post_detail', pk=post.pk) else: form = PostForm() return render(request, 'blog/post_edit.html', {'form': form})
Solo quedará ver si todo marcha bien. Hay que ir a la página http://127.0.0.1:8000/post/new/, agregar un title y un text, guárdalo y listo, se anexará el nuevo artículo (post) al blog el cual nos llevará al sitio de post_detail. Es posible que se haya visto el hecho de que no se definió el periodo de publicación. Es por ello que se incluirá el botón de publicar en Django.
Validando los formularios
Lo que sigue a continuación es verificar que tan bueno están los Django forms. Cualquier artículo (post) dentro del blog debería cargar con los capos de title y text. En este modelo Post no habíamos dicho (con discrepancia de published_date) Que dichos campos son necesarios, por lo que Django, por defecto, esperará a que estén definidos adecuadamente.
Lo que hay que hacer es intentar guardar cada formulario sin title y text.
Django será el encargado de verificar y validad que cada uno de los campos en el formulario esté ordenado correctamente.
Atención: Como hace poco se utilizó la interfaz de administrador en Django, el sistema pensará que ya se está en línea. Existen contexto donde eso pudiese causar la desconexión (haciendo un cierre del navegador, reiniciando la base de datos, etc). En caso de estar en presencia de dicho error al hacer un nuevo artículo (post) que señale el comienzo de inicio de sesión del usuario, hay que ir al sitio de administración http://127.0.0.1:8000/admin para volver a iniciar sesión. Sin duda alguna, el problema se habrá marchado por ahora.
Editar el formulario
Ya que se sabe la manera de añadir un nuevo formulario, es momento de pasar a editarlo. Es bastante parecido a lo que se hizo recientemente. Simplemente se crearán varias cosillas relevantes de manera rápida (en caso de no entender algo, consultar con un experto).
Abrir el archivo blog/templates/blog/post_detail.html y añadir la siguiente línea.
<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
De esa forma, quedará así:
</pre> {% extends 'blog/base.html' %} {% block content %} <div class="date"> {% if post.published_date %} {{ post.published_date }} {% endif %} <a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a> </div> <h1>{{ post.title }}</h1> <p>{{ post.text|linebreaksbr }}</p> {% endblock %} <pre>
Dentro del archivo blog/urls.py se agregará esta línea:
url(r'^post/(?P<pk>[0-9]+)/edit/$', views.post_edit, name='post_edit'),
Lo que sigue a continuación es re-usar la plantilla blog/templates/blog/post_edit.html, faltando solamente una view.
Se debe abrir el archivo blog/views.py y agregar la siguiente línea:
def post_edit(request, pk): post = get_object_or_404(Post, pk=pk) if request.method == "POST": form = PostForm(request.POST, instance=post) if form.is_valid(): post = form.save(commit=False) post.author = request.user post.save() return redirect('post_detail', pk=post.pk) else: form = PostForm(instance=post) return render(request, 'blog/post_edit.html', {'form': form})
Se verá casi igual que la view de post_new sin embargo, solo es una semejanza. Primeramente, hay que pasar un ajuste extra pk en los URLS. Después, obtener el modelo de Post que se desea editar utilizando
get_object_or_404(Post, pk=pk) finalmente, al hacer dicho formulario, se pasará al post como una instancia en el instante que se guarda el formulario:
form = PostForm(request.POST, instance=post)
Esta es la manera de abrir el formulario con el post para poder editar sobre él:
form = PostForm(instance=post)
Ahora, lo siguiente es ver si todo ha ido bien. Hay que ir al sitio de post_detail. Debería existir un botón allí para poder editar, se encontrará en la parte de arriba a la derecha:
Cuando se le da clic a dicho botón, debería aparecer el formulario con el artículo (post) del blog:
Ahora sí, ya se puede modificar el título o texto y salvar los ajustes.
Para terminar, considerar la implementación
Es hora de ver si todo va bien en PythonAnywhere. Es momento de realizar el despliegue.
- Lo primero es hacer un commit con el nuevo código y subirlo a GitHub.
$ git status $ git add --all . $ git status $ git commit -m "Added views to create/edit blog post inside the site." $ git push
- Después, en la consola Bash de PythonAnywhere
$ cd my-first-blog $ git pull [...]
- Para terminar, ir a la pestaña Web y hacer clic en Reload.
Curso de Desarrollo Web con Django