¿Qué son, y cómo crear formularios en Django 6?

Video thumbnail

Índice de contenido

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

Video thumbnail

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.

1. ⚙️ ModelForm (Formularios Ligados a Modelos)

Los ModelForm son formularios que están directamente atados a un modelo de la base de datos.

Ventajas:

  • Automático: Son perfectos para crear procesos CRUD (Crear, Leer, Actualizar, Eliminar) simples, como los que hemos utilizado para comentarios, posts o categorías.
  • Relación Directa: La definición de los campos se extrae automáticamente del modelo, lo que reduce el código (simplemente declaras la tupla fields o __all__).
  • Validaciones Implícitas: Heredan automáticamente las validaciones definidas en el modelo.

Desventajas:

  • Limitación: Están muy ligados a una única entidad.

2. Form (Formularios Estándar)

Los Form (formularios normales de Django) son formularios que no están asociados a ningún modelo específico de la base de datos.

Ventajas:

  • Flexibilidad: Son más genéricos y te dan el 100% del control sobre cada campo que deseas mostrar.
  • Casos Complejos: Ideales para escenarios complejos, como llenar dos o tres entidades diferentes en una sola pantalla, o mostrar campos que no están definidos en ningún modelo en particular.

Desventajas:

  • Mayor Esfuerzo: Son más manuales, lo que se traduce en más código, más trabajo y una mayor propensión a errores.

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.py

Crear 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.

Video thumbnail

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:

Formulario básico en Django
Formulario básico en Django

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:

Error 403
Error 403

Falta el Token de Seguridad: Por defecto, Django requiere un token CSRF (Cross-Site Request Forgery) en todos los formularios que usan el método POST. Este token es esencial para proteger tu sitio de ataques.

Protección CSRF

Video thumbnail

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.

¿Qué es un Ataque CSRF?

Básicamente, un atacante podría crear una aplicación o sitio web (atacante.com) que apunta a un recurso de creación de nuestra aplicación (una URL de producción). Mediante un formulario falsificado, el atacante puede enviar solicitudes a nuestra aplicación, haciéndolas pasar como si hubieran sido generadas por nuestro propio sitio. Esto representa un grave problema de seguridad.

Determinar el tipo de petición desde la vista: GET y POST

Video thumbnail

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.method

Que 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.  

Obtener los datos desde el objeto request

Video thumbnail

Como hemos mencionado, toda la solicitud del usuario viaja dentro del objeto request. Esto incluye la IP, los headers, y, lo más importante para nosotros ahora, los datos enviados por el formulario (POST) o la URL (GET).

Accediendo a los Datos POST y GET

En Django, para obtener los datos enviados, utilizamos las propiedades request.POST o request.GET. Estas propiedades se comportan como diccionarios, permitiéndonos acceder a los valores mediante la clave (el nombre del campo HTML).

Método                                          Propósito                                                              Viaje de Datos
request.POST    Para datos enviados por formularios (method="POST").    Viajan en el cuerpo de la petición (ocultos).
request.GET      Para datos enviados por query parameters (la URL).            Viajan en la URL (ej. ?campo=valor).

La sintaxis para obtener el valor de un campo es:

data = request.<METODO>['<NOMBRE_DEL_CAMPO>']

Es decir, desde el request, podemos obtener los datos con:

request.GET.get(<nombreCampo>)

Para las peticiones de tipo GET.

request.POST.get(<nombreCampo>)

Para las peticiones de tipo POST.

Estructura Condicional en la Vista

Para nuestro formulario de comentarios (que es de tipo POST), usamos request.POST:

Referencia al Campo: Es crucial que la clave utilizada aquí (ej. 'text') coincida con el atributo name que definimos en la etiqueta <textarea> de nuestro formulario HTML.

Obtener el Valor:

if request.method == 'POST':
   print(request.POST.get('text'))
   return

Con esto, si pasas datos mediante el TEXTAREA de tu formulario, verás el contenido por la terminal.

Aunque la sintaxis request.POST['text'] funciona, una forma más robusta y segura es usar el método .get() del diccionario (request.POST.get('text')).

request.POST.get('text'): Si la clave 'text' no existe en la petición, este método devuelve None en lugar de lanzar un error, lo que mejora la gestión de excepciones.

Data Persistence: Saving with the Model

Video thumbnail

To perform database operations, we have to use models; for this, we must have the reference in the record we want to operate based on an object; for example, to save a new record, we have to create an instance of the model class; for example:

comment = Comment()

And with this, we can access its attributes; for example:

comment.text

With this, we can set values or consume them; and then, register them in the database; for example:

comment.save()

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.

Clase Meta (Metadatos)

La Clase Meta es una convención de Django (y Python) que se usa para definir metadatos (datos sobre la clase) en lugar de atributos de instancia, ya que la clase global (CommentForm) por sí sola no hace nada.

  • model: Especifica el modelo al cual está enlazado el formulario (Comment).
  • fields: Define qué campos del modelo se deben incluir. Si tienes 20 campos en el modelo, y necesitas todos, los incluyes aquí. También puedes excluir campos autogenerados.
    • Sintaxis de Tupla: Recuerda que si solo incluyes un elemento en fields, debes añadir una coma final (['text',]) para que Python lo trate correctamente como una tupla o lista de un solo elemento, y no como un simple string.

Este formulario será nuestra nueva capa intermedia que se encargará de procesar y validar los datos antes de guardarlos en la base de datos. Veremos cómo utilizarlo en la siguiente clase.

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

Video thumbnail

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:

Formulario Django

Y verás en tu base de datos:

Bade de datos

Si colocas datos inválidos, es decir un formulario sin valores, verás que salta una validación del lado del cliente:

Error validación cliente formulario

El template:

comments\templates\comments\add.html

    <form action="" method="post">
        {% csrf_token %}
        {{ form }}
        <button type="submit">Send</button>
    </form>

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-forms

Agrega 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

Video thumbnail

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.

Video thumbnail

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 })
Video thumbnail

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

Video thumbnail

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>

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 bloques 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.

Implementar Operaciones CRUD en nuestra aplicación en Django 6

Video thumbnail

A continuación, implementaremos las operaciones faltantes del CRUD (Listado, Actualización y Eliminación) en las vistas, rutas y templates, utilizando los conocimientos que ya tenemos sobre el ORM y los formularios.

1. Listado de Registros (Read)

Esta operación requiere obtener todos los comentarios y pasarlos a un template de listado.

  • Vista (views.py):
    • Definimos la función index(request).
    • Usamos Comment.objects.all() para obtener todos los registros.
    • Renderizamos el template y pasamos el QuerySet como contexto.
  • Ruta (urls.py):
    • Definimos la ruta principal (ej. path('', views.index, name='index')).
    • Template (comments/index.html):
    • Usamos la directiva {% for ... in ... %} de Django Template Language para iterar sobre el listado de comentarios.
    • Mostramos los atributos (ej. {{ comment.text }}, {{ comment.date_posted }}).

En views.py

def index(request):
   comments = Comment.objects.all()
   context = {'comments': comments}
   return render(request, 'comments/index.html', context)

2. ✏️ Actualizar Registro (Update)

La actualización es la operación más compleja, ya que debe manejar GET (cargar datos) y POST (guardar cambios).

Ruta (urls.py):

La ruta debe recibir el identificador único del registro a actualizar (ej. la llave primaria o PK).

path('update/<int:pk>/', views.update, name='update')

Vista (views.py):

La función update(request, pk) debe recibir la pk como argumento.

  • Lógica GET: Usamos Comment.objects.get(pk=pk) para obtener el comentario (o idealmente get_object_or_404). Creamos una instancia del CommentForm con ese objeto: form = CommentForm(instance=comment).
  • Lógica POST: Creamos la instancia con los datos request.POST y la instancia del modelo: form = CommentForm(request.POST, instance=comment). Si es válido (.is_valid()), .save() actualiza el registro existente.

Importante: Usar instance=comment en el formulario es lo que le indica a Django que debe actualizar el objeto existente en lugar de crear uno nuevo.

3. ️ Eliminación de Registro (Delete)

Para seguir las buenas convenciones HTTP, la eliminación se realiza mediante una petición POST.

Ruta (urls.py):

path('delete/<int:pk>/', views.delete, name='delete')

Vista (views.py):

  • La función delete(request, pk) solo debe procesar la petición si es POST.
  • Obtenemos el comentario con la pk.
  • Llamamos al método de ORM: comment.delete().
  • Acción Final: Después de eliminar, el usuario debe ser redirigido (ej. al listado).

4. Enlaces y Formularios de Acción en index.html

Finalmente, en el template de listado, definimos los enlaces dinámicos usando la directiva {% url %}:

Enlace de Actualización: Apunta a la ruta update usando la PK del comentario.

<a href="{% url 'update' c.id %}">Editar</a>

Formulario de Eliminación: Para seguir la convención POST, se usa un mini-formulario con el token CSRF que apunta a la ruta delete.

<form method="POST" action="{% url 'delete' c.id %}">
   {% csrf_token %}
   <button type="submit">Eliminar</button>
</form>

Con estos pasos, hemos completado el ciclo CRUD, integrando modelos, vistas, rutas y formularios.

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.

Aprende a crear y gestionar formularios en Django paso a paso. Cubrimos desde la clase Form y ModelForm hasta la validación de datos y protección CSRF.

| 👤 Andrés Cruz

🇺🇸 In english