Modelos en Django: ORM y Base de Datos

El ORM (Object-Relational Mapping) de Django permite interactuar con bases de datos utilizando código Python, abstrayendo la complejidad de las consultas SQL.

  Características Principales

  • Mapeo directo entre clases Python y tablas de base de datos
  • Soporte para múltiples bases de datos (PostgreSQL, MySQL, SQLite, Oracle)
  • Generación automática de esquemas
  • Validación de datos integrada
  • Consultas dinámicas y encadenables

1Estructura Básica de un Modelo
python
from django.db import models
from django.core.validators import MinLengthValidator, EmailValidator

class Usuario(models.Model):
  # Campos de texto
  nombre = models.CharField(
      max_length=100, 
      validators=[MinLengthValidator(2)]
  )
  email = models.EmailField(
      unique=True, 
      validators=[EmailValidator()]
  )
  
  # Campos numéricos
  edad = models.PositiveIntegerField(null=True, blank=True)
  
  # Campos de fecha
  fecha_registro = models.DateTimeField(auto_now_add=True)
  
  # Campos booleanos
  is_activo = models.BooleanField(default=True)
  
  # Campos con relaciones
  perfil = models.OneToOneField(
      'Perfil', 
      on_delete=models.CASCADE, 
      null=True
  )

  class Meta:
      verbose_name = 'Usuario'
      verbose_name_plural = 'Usuarios'
      ordering = ['-fecha_registro']

  def __str__(self):
      return self.nombre
2Tipos de Campos Especializados
python
class Producto(models.Model):
  # Campos con opciones predefinidas
  CATEGORIAS = [
      ('electronica', 'Electrónica'),
      ('ropa', 'Ropa'),
      ('alimentos', 'Alimentos')
  ]

  nombre = models.CharField(max_length=200)
  precio = models.DecimalField(max_digits=10, decimal_places=2)
  descripcion = models.TextField(blank=True)
  
  # Campo con choices
  categoria = models.CharField(
      max_length=20, 
      choices=CATEGORIAS
  )
  
  # Campo de archivo
  imagen = models.ImageField(
      upload_to='productos/', 
      null=True, 
      blank=True
  )
3Tipos de Relaciones entre Modelos
python
class Autor(models.Model):
  nombre = models.CharField(max_length=100)

class Libro(models.Model):
  # Relación Many-to-One
  autor = models.ForeignKey(
      Autor, 
      on_delete=models.CASCADE,
      related_name='libros'
  )

class Biblioteca(models.Model):
  # Relación Many-to-Many
  libros = models.ManyToManyField(
      Libro, 
      related_name='bibliotecas'
  )
4Migraciones y Gestión de Base de Datos
bash
# Crear migraciones (detecta cambios en modelos)
python manage.py makemigrations

# Ver migraciones pendientes
python manage.py showmigrations

# Aplicar migraciones
python manage.py migrate

# Migración para una app específica
python manage.py migrate usuarios

# Revertir migración
python manage.py migrate usuarios 0001
5Migraciones Personalizadas
python
from django.db import migrations, models

class Migration(migrations.Migration):
  dependencies = [
      ('usuarios', '0001_initial'),
  ]

  operations = [
      migrations.AddField(
          model_name='usuario',
          name='nuevo_campo',
          field=models.CharField(max_length=50, null=True),
      ),
  ]
6Consultas Avanzadas con ORM
python
# Consultas básicas
usuarios = Usuario.objects.all()
usuario = Usuario.objects.get(id=1)

# Filtrado
usuarios_activos = Usuario.objects.filter(is_activo=True)

# Consultas complejas
usuarios_filtrados = Usuario.objects.filter(
  edad__gte=18
).exclude(
  nombre__startswith='A'
).order_by('-fecha_registro')

# Agregaciones
from django.db.models import Count, Avg, Sum
total_usuarios = Usuario.objects.count()
promedio_edad = Usuario.objects.aggregate(Avg('edad'))
7Validaciones y Restricciones
python
from django.core.exceptions import ValidationError
from django.core.validators import MinValueValidator

class Pedido(models.Model):
  cantidad = models.IntegerField(
      validators=[MinValueValidator(1, 'La cantidad debe ser mayor a 0')]
  )

  def clean(self):
      # Validación personalizada
      if self.cantidad > 100:
          raise ValidationError('Cantidad máxima excedida')
  Buenas Prácticas

  • Usar __str__() para representación legible
  • Aprovechar Meta para configuraciones adicionales
  • Mantener modelos delgados, lógica de negocio en servicios
  • Usar migraciones para evolución de esquema
  • Validar datos en el modelo