En este post, exploraremos cómo manejar relaciones uno a muchos en Django utilizando modelos, formularios y vistas. Tomaremos como ejemplo dos modelos: Cliente y ClientesActividades, donde un cliente puede tener múltiples actividades asociadas.
1. Definición de los Modelos
Comenzamos definiendo los modelos en Django. El modelo Cliente
representa a un cliente, mientras que ClientesActividades
almacena las actividades relacionadas con cada cliente. Usamos una clave foránea (ForeignKey
) para establecer la relación.
from django.db import models
class Cliente(models.Model):
cedula = models.CharField(max_length=20)
nombre = models.CharField(max_length=100)
apellido = models.CharField(max_length=100)
timbrado = models.CharField(max_length=50, blank=True, null=True)
celular = models.CharField(max_length=20, blank=True, null=True)
email = models.CharField(max_length=100, blank=True, null=True)
direccion = models.CharField(max_length=200, blank=True, null=True)
class Meta:
db_table = 'clientes'
def __str__(self):
return f"{self.nombre} {self.apellido}"
class ClientesActividades(models.Model):
cliente = models.ForeignKey(Cliente, on_delete=models.CASCADE, related_name='actividades')
actividad = models.IntegerField(blank=True, null=True)
class Meta:
db_table = 'clientes_actividades'
def __str__(self):
return f"Actividad {self.actividad} de {self.cliente.nombre}"
2. Creación de Formularios
Para manejar la creación y edición de clientes junto con sus actividades, utilizamos formularios y un inlineformset_factory
.
Esto nos permite gestionar múltiples actividades relacionadas con un cliente en un solo formulario.
from django import forms
from .models import Cliente, ClientesActividades
from django.forms import inlineformset_factory
class ClienteForm(forms.ModelForm):
class Meta:
model = Cliente
fields = ['cedula', 'nombre', 'apellido', 'timbrado', 'celular', 'email', 'direccion']
class ClientesActividadesForm(forms.ModelForm):
class Meta:
model = ClientesActividades
fields = ['actividad']
# Creamos un formset para las actividades
ClientesActividadesFormSet = inlineformset_factory(
Cliente, # Modelo principal
ClientesActividades, # Modelo relacionado
form=ClientesActividadesForm, # Formulario para el modelo relacionado
extra=1, # Número de formularios vacíos que se muestran por defecto
can_delete=True # Permite eliminar actividades
)
3. Vistas para Crear y Editar Clientes
Las vistas manejan la lógica para crear y editar clientes junto con sus actividades. Usamos el formset
para gestionar las actividades relacionadas.
from django.shortcuts import render, redirect, get_object_or_404
from .models import Cliente, ClientesActividades
from .forms import ClienteForm, ClientesActividadesFormSet
def crear_cliente(request):
if request.method == 'POST':
form = ClienteForm(request.POST)
formset = ClientesActividadesFormSet(request.POST)
if form.is_valid() and formset.is_valid():
cliente = form.save() # Guarda el cliente
formset.instance = cliente # Asocia el formset con el cliente
formset.save() # Guarda las actividades relacionadas
return redirect('lista_clientes') # Redirige a la lista de clientes
else:
form = ClienteForm()
formset = ClientesActividadesFormSet()
return render(request, 'crear_cliente.html', {'form': form, 'formset': formset})
def editar_cliente(request, cliente_id):
cliente = get_object_or_404(Cliente, id=cliente_id)
if request.method == 'POST':
form = ClienteForm(request.POST, instance=cliente)
formset = ClientesActividadesFormSet(request.POST, instance=cliente)
if form.is_valid() and formset.is_valid():
form.save()
formset.save()
return redirect('lista_clientes')
else:
form = ClienteForm(instance=cliente)
formset = ClientesActividadesFormSet(instance=cliente)
return render(request, 'editar_cliente.html', {'form': form, 'formset': formset})
4. Plantillas
Las plantillas muestran los formularios para crear y editar clientes, así como la lista de clientes.
<!-- crear_cliente.html -->
<form method="post">
{% csrf_token %}
{{ form.as_p }} <!-- Formulario del cliente -->
<h3>Actividades</h3>
{{ formset.management_form }} <!-- Gestión del formset -->
{% for form in formset %}
<div class="actividad-form">
{{ form.as_p }} <!-- Formulario de cada actividad -->
</div>
{% endfor %}
<button type="submit">Guardar</button>
</form>
Conclusión
Este enfoque permite manejar relaciones uno a muchos en Django de manera eficiente, utilizando formularios y vistas para gestionar tanto el modelo principal como los modelos relacionados. Es una técnica útil para aplicaciones que requieren la gestión de datos complejos.
Comentarios
Publicar un comentario