¿Qué son, y cómo crear formularios en Django?
Índice de contenido
- ¿Qué es un formulario en Django y para qué sirve?
- La clase Form y su papel en el framework
- Diferencias entre Form y ModelForm
- Ventajas de usar formularios nativos de Django
- ¿Para que se utilizan los formularios en Django?
- ¿Cómo crear un formulario en Django?
- ¿Cómo envía Django los datos del formulario?
- ¿Qué es Django crispy forms?
- ¿Tengo que usar formularios de Django?
- ️ Estructura básica del proyecto: dónde definir tus formularios
- Crear un formulario en Django
- Explicación del código anterior
- Campos de formulario
- Render del formulario
- ⚙️ Procesar y validar datos desde el formulario
- Uso de is_valid() y cleaned_data
- Guardar los datos en la base de datos
- Manejo de errores
- Conclusiones
- Peticiones GET y POST y tokens CSRF
- Protección CSRF
- Determinar el tipo de petición desde la vista: GET y POST
- Formularios basados en modelos: ModelForm
- Procesar formularios
- Caso práctico
- Mejorar el diseño con django-crispy-forms
- Cómo crear un Textarea en un formulario Django
- ¿Cómo podemos crear un área de texto en Django?
- Buenas prácticas y recomendaciones personales
- Trabajando con formularios ModelForm en Django, crear un registro
- Formularios de tipo get y post
- Código completo de la aplicación
- Conclusiones
- ❓ Preguntas frecuentes (FAQs)
Cuando desarrollamos con Django, llega un punto en que no solo necesitamos eliminar datos en Django, si no también necesitamos recibir datos del usuario y : registros, comentarios, búsquedas o cargas de archivos. En mi experiencia, entender cómo crear formularios en Django marca el salto de principiante a desarrollador funcional.
Vamos a crear un formulario en Django, lo cual es un elemento fundamental ya cuando sabemos dar los primeros pasos en Django, conocer como crear un proyecto, el manejo de las rutas y dar los primeros pasos con nuestro MTV; antes de comenzar, vamos a hablar sobre los formularios.
¿Qué es un formulario en Django y para qué sirve?
Django proporciona una clase Form que se utiliza para crear formularios HTML, o mejor dicho, sus campos, ya que con los mismos podemos describir cuales son los campos, de qué tipo (enteros, flotantes, campos de textos, listados...) y cómo funciona y aparece. Es similar a la clase ModelForm que crea un formulario utilizando el modelo, pero no requiere el modelo, por lo tanto, son más manuales y flexibles que estos últimos.
Un formulario en Django es una clase de Python que representa una estructura de entrada de datos, mapea campos HTML (<input>, <select>, etc.) y aplica validaciones automáticas.
La clase Form y su papel en el framework
Django proporciona la clase base Form dentro del módulo django.forms. Con ella puedes definir los campos, sus tipos y validaciones.
Por ejemplo:
from django import forms
class ContactForm(forms.Form):
name = forms.CharField(max_length=100, required=True)
email = forms.EmailField(required=True)
message = forms.CharField(widget=forms.Textarea)Diferencias entre Form y ModelForm
Aclaremos para qué usar cada tipo de formulario en Django:
- Form se usa cuando defines los campos manualmente.
- ModelForm se vincula a un modelo existente y genera los campos automáticamente.
Si necesitas control total, usa Form. Si tu formulario está ligado a un modelo (usuarios, productos, etc.), ModelForm te ahorra tiempo.
Ventajas de usar formularios nativos de Django
En mi caso, descubrí que usar formularios nativos simplifica la validación, evita repetir lógica y mejora la seguridad (CSRF, saneamiento de datos, validación tanto en cliente como servidor).
¿Para que se utilizan los formularios en Django?
Los formularios se utilizan básicamente para recibir información del usuario de alguna manera y utilizar esa información para operaciones lógicas en bases de datos. Por ejemplo, registrar un usuario tomando como entrada su nombre, correo electrónico, contraseña, etc. Django mapea los campos definidos en los formularios de Django en campos de entrada HTML.
De tal manera que con una sola definición (formularios en Django) tenemos tanto el render en HTML de los campos como el manejo en las vistas/controladores y por supuesto, validaciones en ambos lados.
¿Cómo crear un formulario en Django?
Los datos del formulario se almacenan en el archivo llamado como forms.py por convención, es decir, que el archivo puede tener cualquier otro nombre, pero generalmente lo llamamos cono forms; este formulario se almacena a nivel de una aplicación (dentro del directorio de la aplicación); por lo tanto, cada aplicación puede definir sus propios formularios según el esquema que quieras darle.
¿Cómo envía Django los datos del formulario?
En Django, el objeto de solicitud que se pasa como parámetro a su vista tiene un atributo llamado "método" donde se establece el tipo de solicitud y se puede acceder a todos los datos pasados a través de POST a través de la solicitud en forma de un diccionario.
¿Qué es Django crispy forms?
Este también es una duda común, django-crispy-forms no es más que un filtro | crispy y una etiqueta {% crispy %} que le permitirá controlar el comportamiento de renderizado de sus formularios Django de una manera muy elegante y SECA. Para tener el control total sin escribir plantillas de formulario personalizadas y con esto, podemos por ejemplo definir clases que queramos que tenga nuestro formulario, por ejemplo, las de Bootstrap o las de Tailwind o las propias.
¿Tengo que usar formularios de Django?
Finalmente, la pregunta del millón; La recomendación es que uses los formularios de Django, ya que son bastante fáciles de usar y manejan toda la validación por usted (use required = True en cada campo, y ya está listo para la simple verificación 'no en blanco' que mencionó), son fáciles de obtener los datos, sanearlos, verificar estado y TODO esto lo perderías si NO los empleamos.
️ Estructura básica del proyecto: dónde definir tus formularios
Por convención, los formularios se definen dentro del archivo forms.py de cada aplicación. Esto mantiene tu proyecto ordenado y modular.
El archivo forms.py y su ubicación
Cada app en Django puede tener su propio forms.py:
/mi_proyecto/
/productos/
forms.py
models.py
views.pyCrear un formulario en Django
Como mencionamos al inicio de este bloque, vamos a crear un formulario en Django, para eso, como comentamos, creamos un archivo llamado forms.py en el cual vamos a definir formularios a nivel de clases:
from django import forms
from .models import Category
class ProductsForm(forms.Form):
title = forms.CharField(label="Nombre", required=True, max_length=255, min_length=3)
description = forms.CharField(label="Descripción",widget=forms.Textarea(attrs={"rows":5, "cols":20}))
price = forms.FloatField(required=True, min_value=0.1)
category = forms.ModelChoiceField(label="Categoría", queryset=Category.objects.all())Explicación del código anterior
Como puedes ver, definiendo una clase que herede de forms.Form (donde forms es un módulo que importamos desde Django) podemos definir una clase en base a formulario, en donde cada propiedad de la clase es un campo de formulario... así de simple.
Campos de formulario
Tenemos TODO tipo de campos, de tipo texto, números, seleccionables, archivos... en este caso estamos empleando algunos de tipo texto (titulo y descripción) uno de tipo numero (precio) y otro de tipo seleccionable, indicando un modelo (categoría)
- En la misma definición de los campos, indicamos algunas validaciones como tamaño máximo, mínimo y si es requerido.
- También indicamos el label, por lo tanto, con una sola propiedad, podemos definir tanto label como campo.
Vamos a crear una función de creación, para el formulario, aunque perfectamente puedes adaptar el formulario para el proceso de edición o actualización de registros en Django:
def create(request):
form = ProductsForm()
return render(request, 'create.html', { 'form' : form })Como puedes ver, creamos una instancia del formulario y se lo pasamos a un template:
Render del formulario
Cada campo define su validación. Con una sola clase tienes control sobre etiquetas, tipos y comportamiento visual.
Mostrar el formulario en una vista
def create(request):
form = ProductsForm()
return render(request, 'create.html', {'form': form})Para renderizarlo en una vista/template, podemos usar el formulario que pasamos como parámetros desde el views.py:
<form method="post">
{% csrf_token %}
{{ form }}
<button type="submit">Enviar</button>
</form>Inclusive preguntar por campos en particulares:
{{form.price}}O el Label
{{form.price.label}}Por si quieres construir los campos uno por uno.
⚙️ Procesar y validar datos desde el formulario
Una de las partes que más me ayudó a entender Django fue su flujo de validación.
Cómo Django maneja POST y GET
Al enviar un formulario, los datos llegan a la vista mediante request.POST.
Para procesarlos:
def create(request):
if request.method == 'POST':
form = ProductsForm(request.POST)
if form.is_valid():
print("Datos válidos")Uso de is_valid() y cleaned_data
form.is_valid() comprueba las validaciones definidas en los campos. Si todo está correcto, puedes acceder a los datos saneados en form.cleaned_data.
Guardar los datos en la base de datos
En mi experiencia, lo más limpio es crear una instancia del modelo:
product = Product()
product.title = form.cleaned_data['title']
product.price = form.cleaned_data['price']
product.save()Manejo de errores
Si los datos no son válidos, Django devuelve el formulario con los mensajes de error, sin que tengas que reescribir nada.
Conclusiones
Los formularios son un mecanismo que tenemos para trabajar de una manera efectiva con los datos del usuario, los podemos emplear en distintos propósitos y Django nos da todo la flexibilidad y sencillez que lo caracteriza para trabajar con los formularios de una manera efectiva y extensible.
Peticiones GET y POST y tokens CSRF
Para explicar para qué usar los tokens CSRF, vamos a hacer un pequeño ejercicio.
Vamos a crear una función llamada add(), para agregar comentarios; de momento, el apartado para dibujar una vista:
def add(request):
return render(request,'add.html')Tenemos que crea una página:
comments/templates/add.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>Page to add</h1>
</body>
</html>Podemos crear rutas en cada aplicación que luego registramos en el proyecto; vamos a crear un archivo llamado urls.py con el siguiente contenido:
comments/urls.py
from django.urls import path
from . import views
app_name='comments'
urlpatterns = [
path('add', views.add, name='add')
]Ahora, vamos a crear un formulario en HTML para crear un comentario:
templates/comments/add.html
<form method="post">
<label for="id_text">Text:</label>
<textarea name="text" cols="40" rows="10" class="form-input" required id="id_text">
</textarea>
<input type="submit" value="Enviar">
</form>Lucirá como:
El formulario es realmente sencillo, tenemos un formulario de tipo POST que apunta a la ruta de /comments/add que es la función de vista de llamada add(), la cual es la misma que se encarga de pintar este formulario.
Al enviar el formulario veremos un error como el siguiente:
Protección CSRF
El error anterior pasa ya que, Django para evitar el Cross-site request forgery o falsificación de petición en sitios cruzados emplea un token que genera e inyecta en los formularios; así que, para poder emplear este token, basta con emplear la siguiente directiva:
Indicamos el token:
<form method="post">
{% csrf_token %}
***
<input type="submit" value="Send">
</form>Y con esto, la petición ya pasaría.
Determinar el tipo de petición desde la vista: GET y POST
Usualmente, cuando queremos cambiar el modelo de datos del proyecto, en este caso, crear un elemento, usamos una petición de tipo POST desde los formularios de HTML:
- Las peticiones de tipo GET se usan para consultar datos.
- Las peticiones de tipo POST se usan para cambiar el modelo de datos, entiéndase para crear, actualizar o eliminar.
Ahora, tenemos que recibir esta petición de tipo POST desde la función de vista; para eso, tenemos que manejar la petición o request del usuario, que es el parámetro que recibimos por defecto en las funciones de vistas; por ejemplo:
def add(request):
return render(request,'comments/add.html')Mediante:
request.methodQue nos devuelve el tipo de petición; GET o POST.
Con esto, podemos obtener todo lo que tenga que ver con la petición que hizo nuestro usuario desde la página web mediante el formulario; como los headers, tipo de petición y por supuesto, los datos del formulario.
Como la función de add() la vamos a usar para manejar ambos tipos de peticiones:
- Petición de tipo GET, para pintar la página HTML mediante el template.
- Petición de tipo POST, para procesar los datos del formulario.
Así que, para determinar el proceso que vamos a ejecutar según un tipo de petición, tenemos:
request.method == 'POST'Y el código queda de la siguiente manera:
def add(request):
if request.method == 'POST':
print("Estamos en el post")
return
return render(request,'comments/add.html')- Si la petición es de GET, pintamos el formulario mediante el template.
- Si la petición es de tipo POST, imprimimos un mensaje por la terminal.
Si envías el formulario, por el navegador debes de ver una excepción de tipo ValueError que indica que no es una respuesta HTTP válida; ya que, no estamos devolviendo nada; pero, por la terminal, veremos el mensaje de:
Estamos en el post
De momento logramos enviar datos a nuestra función de vista con la cual la estamos imprimiendo por consola; pero, cómo podemos crear un registro en la base de datos; para eso, necesitamos conocer la manera en la cual podemos obtener estos datos desde el request.
Formularios basados en modelos: ModelForm
Los modelos para los formularios son clases que definen la estructura en base a una clase en Python con sus atributos correspondientes; dichas clases permiten:
- Definir la estructura del formulario.
- Aplicar validaciones del lado del servidor y del cliente.
- Poder reutilizar los formularios fácilmente.
Para usar los formularios, los podemos definir en un archivo aparte a nivel de la aplicación; que por convención se llama cómo forms.py.
Con esto en mente, vamos a crear la siguiente clase:
comments/forms.py
from django.forms import ModelForm, Textarea
from .models import Comment
class CommentForm(ModelForm):
class Meta:
model = Comment
fields = ('text',)Gracias a ModelForm, puedes ahorrar muchas líneas y mantener la lógica centrada en el modelo.
Explicación del código anterior
Los formularios de tipo ModelForm nos ofrecen un esquema sencillo para definir campos del formulario; como puedes ver, es una clase en Python que hereda de la mencionada clase.
Luego, tenemos que definir dentro de esta clase formulario, una clase llamada Meta, para definir la estructura de los formularios; es decir, a qué modelos está relacionado este formulario, y cuáles son los campos; los campos no son más que una tupla de Python.
Estas clases son muy personalizables y puedes definir procesos de guardados, inicialización a nivel de clases, definir atributos, personalizar campos de formularios, validaciones, entre otros; aunque de momento, tenemos un ejemplo mínimo.
Para las clases modelos, viene siendo lo usual, crear una instancia y en este caso, pasar al template.
Vamos a ir a la función de add(), y lo pasamos como segundo parámetro, el formulario:
from .forms import CommentForm
// ***
form = CommentForm()
return render(request,'comments/add.html',{'form':form})Desde nuestro template, podemos imprimir el formulario completo:
{{ form }}Y con esto, aparecen todos los campos que hayas definido junto con el LABEL:
O por campos, de manera independiente:
{{ form.text }}Usa el que mejor te parezca y convenga.
Procesar formularios
Desde el request, podemos obtener los datos del formulario que estamos enviando vía POST o GET tal cual vimos anteriormente; así que, para establecer los datos que van vía POST en el formulario anterior:
form = Formulario(request.POST)Se lo pasamos como inicialización al formulario.
Caso práctico
La función de add() va a quedar de la siguiente manera:
def add(request):
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save()
else:
form = CommentForm()
return render(request,'comments/add.html',{'form':form})Como puedes ver en el código anterior, desde el mismo modelo, podemos hacer uso de la función de save() para crear un comentario.
Con esto, puedes realizar algunas pruebas y enviar datos desde el formulario del template:
Y verás en tu base de datos:
Si colocas datos inválidos, es decir un formulario sin valores, verás que salta una validación del lado del cliente:
Mejorar el diseño con django-crispy-forms
Si alguna vez has intentado alinear campos manualmente, sabrás que puede ser tedioso.
django-crispy-forms te da un control visual elegante y limpio.
Instalación y configuración básica
$ pip install django-crispy-formsAgrega en settings.py:
INSTALLED_APPS = ['crispy_forms']Integración con Bootstrap o Tailwind
En tus plantillas:
{% load crispy_forms_tags %}
<form method="post">
{% csrf_token %}
{% crispy form %}
</form>Ejemplo estilizado
Puedes incluso aplicar clases Bootstrap sin escribir HTML adicional.
Cómo crear un Textarea en un formulario Django
¿Cómo podemos crear un área de texto en Django?
El siguiente código a continuación se puede utilizar para crear un área de texto en un formulario Django:
comment= forms.CharField(widget=forms.Textarea)También podemos personalizar los atributos, como en este caso serían las filas y columnas:
comment= forms.CharField(widget=forms.Textarea(attrs={"rows":8, "cols":10})En este ejemplo, creamos un textarea con 8 filas y 10 columnas.
Buenas prácticas y recomendaciones personales
- Organiza tus formularios: agrúpalos por módulo o modelo.
- Valida siempre en ambos lados: el cliente (HTML5) y el servidor (Django).
- Usa crispy-forms o widgets: mejoran la experiencia visual.
- Debug: si un formulario no valida, imprime form.errors para saber por qué.
Trabajando con formularios ModelForm en Django, crear un registro
En HTML, un formulario es una colección de elementos dentro de <form>...</form> que permiten a un usuario ingresar texto, seleccionar opciones, entre cualquier otra operación; etc., y luego devolver esa información. al servidor, en este caso, a Django.
Algunos de estos elementos de interfaz de formulario (entrada de texto o casillas de verificación) están incrustados en el propio HTML. Otros son mucho más complejos; Una interfaz que muestra un selector de fechas o le permite mover un control deslizante o manipular controles generalmente usará JavaScript y CSS, así como también elementos de formulario HTML <input> para lograr estos efectos.
Vamos a crear el proceso para emplear el formulario para crear registros empleando el Form en Django:
class ProductForm(forms.ModelForm):
class Meta:
model = Product
fields = ('title','subtitle','slug','post', 'path','content','description','posted','product_type', 'date','image', 'user', 'price_offert', 'price')
widgets = {
'description': forms.Textarea(attrs={'rows': 10, 'cols': 80}),
}Vamos a emplear una función de creación que vamos a emplear tanto para mostrar el formulario como para crear los registros.
def create(request):
form = ProductForm()
return render(request, 'create.html', { 'form' : form })Como puedes ver, creamos una instancia de nuestro formulario, la clase y luego pasamos esta instancia a un template que tiene la siguiente definición:
<form method="post">
{% csrf_token %}
{{ form }}
<button type="submit">Enviar</button>
</form>Como puedes ver, imprimimos el form que encapsulamos dentro de un form HTML y lo definimos de tipo Post, ya que las peticiones de tipo POST son las que generalmente empleamos para crear o actualizar registros.
Formularios de tipo get y post
Ahora, queremos emplear este formulario para crear nuestros registros, para eso debemos detectar cuando pintamos el formulario (get) o cuando procesamos los datos (post), para eso detectamos el tipo de método, si es de tipo Post (request.method == "POST"), en este caso, además de, preguntar si el formulario es válido (si las validaciones realizadas fueron superadas), luego, generamos una instancia de product, que es un modelo y establecemos sus datos:
product = Product()
product.title = form.cleaned_data['title']
product.price = form.cleaned_data['price']
product.description = form.cleaned_data['description']
product.category = form.cleaned_data['category']Y luego guardamos:
product.save()cleaned_data nos permite trabajar con los datos saneados.
Código completo de la aplicación
def create(request):
form = ProductForm()
if request.method == "POST":
#print(request.POST['title'])
form = ProductForm(request.POST)
if form.is_valid():
print("Valido")
#form.save()
product = Product()
product.title = form.cleaned_data['title']
product.price = form.cleaned_data['price']
product.description = form.cleaned_data['description']
product.category = form.cleaned_data['category']
product.save()
else:
print("Invalido")
return render(request, 'create.html', { 'form' : form })
<form method="post">
{% csrf_token %}
{{ form }}
<button type="submit">Enviar</button>
</form>En esta entrada, veremos como crear un textarea en un formulario en Django y con esto, tener un area de texto más grande para poder escribir en vez de un input de tipo texto en el cual, solamente podemos escribir textos en una sola línea, muy usadas para crear lboques de comentarios o para escribir alguna descripción y como todo campo en HTML, es perfectamente personalizable a nivel de estilo
Las áreas de texto son comunes para cosas como ingresar comentarios u otra información extensa.
Conclusiones
Crear formularios en Django es una de las habilidades más útiles para cualquier desarrollador backend.
Django te ofrece:
- Validación automática
- Limpieza y saneamiento de datos
- Seguridad incorporada
- Integración fluida con modelos
En mi caso, después de probar múltiples formas de hacerlo, siempre regreso a los formularios nativos de Django: sencillos, seguros y flexibles.
Como puedes darte cuenta, emplear el formulario que creamos en la entrada anterior, resulta sencillo para hacer este tipo de operaciones, en la función de creación cumple dos únicos pasos, pintar el formulario y obtener los datos para registrarlos en el modelo para luego guardarlos.
❓ Preguntas frecuentes (FAQs)
¿Qué diferencia hay entre Form y ModelForm?
Form es manual, ModelForm se basa en modelos. Usa el segundo si el formulario guarda datos en la base.
¿Dónde se define un formulario en Django?
Dentro del archivo forms.py de cada aplicación.
¿Cómo validar un formulario?
Con form.is_valid() y accediendo a los datos limpios con form.cleaned_data.
¿Cómo guardar datos del formulario?
En ModelForm, usa form.save(). En Form, crea y guarda manualmente la instancia del modelo.
¿Qué librería ayuda a mejorar el aspecto visual?
django-crispy-forms, compatible con Bootstrap o Tailwind.
¿Por qué usar el 'forms.py' de Django en lugar de manejar los formularios de la forma normal?
Debido a que con los formularios de Django nos ahorramos mucho trabajo tanto en validaciones como en procesamientos de los mismos en el servidor.
El siguiente paso es aprender como podemos cargar archivos en Django.
Acepto recibir anuncios de interes sobre este Blog.
Vamos a explicar varios aspectos de formularios en Django y como puedes crear un formulario y reenderizarlo en un template.