En Django, interactuar con la base de datos se hace principalmente a través de queries (consultas) utilizando el ORM (Object-Relational Mapping). Esto te permite trabajar con los datos de una manera más orientada a objetos, sin tener que escribir SQL manualmente.
A continuación, definimos algunos modelos fundamentales en Django con los que realizaremos queries esenciales para manipular y consultar datos de manera efectiva:
from django.db import models
class Estudiante(models.Model):
nombre = models.CharField(max_length=100)
edad = models.IntegerField()
curso = models.CharField(max_length=50)
promedio = models.FloatField()
activo = models.BooleanField(default=True)
class Usuario(models.Model):
nombre = models.CharField(max_length=100)
email = models.EmailField(unique=True)
edad = models.IntegerField()
activo = models.BooleanField(default=True)
class Producto(models.Model):
nombre = models.CharField(max_length=200)
precio = models.DecimalField(max_digits=10, decimal_places=2)
stock = models.IntegerField()
categoria = models.CharField(max_length=100)
class Pedido(models.Model):
usuario = models.ForeignKey(Usuario, on_delete=models.CASCADE)
productos = models.ManyToManyField(Producto)
fecha = models.DateTimeField(auto_now_add=True)
total = models.DecimalField(max_digits=10, decimal_places=2) .objects.all() es un método de QuerySet en Django. Permite obtener todos los registros de un modelo de base de datos.
Cuando lo llamas, Django construye y ejecuta una consulta SQL que recupera todas las filas de la tabla asociada al modelo.
Ejemplo 1: Obtener todos los usuarios
todos_usuarios = Usuario.objects.all() Ejemplo 2: Imprimir nombres de todos los usuarios
for usuario in todos_usuarios:
print(usuario.nombre) Ejemplo 3: Convertir a lista
lista_usuarios = list(Usuario.objects.all()) .objects.filter() es un método de QuerySet en Django que permite filtrar registros según condiciones específicas. Retorna un conjunto de registros que coinciden con los criterios de búsqueda definidos. Si no se encuentra ningún registro que cumpla con las condiciones, devuelve un QuerySet vacío.
usuarios_mayores = Usuario.objects.filter(edad__gte=18) Ejemplo 1: Filtrar estudiantes mayores de 18
estudiantes_mayores = Estudiante.objects.filter(edad__gte=18) Ejemplo 2: Filtrar por curso y promedio
estudiantes_matematicas = Estudiante.objects.filter(
curso='Matemáticas',
promedio__gt=8.0
) Ejemplo 3: Filtros combinados
estudiantes_activos_ingenieria = Estudiante.objects.filter(
activo=True,
curso__startswith='Ingeniería'
) Ejemplo 4: Filtros con múltiples condiciones
usuarios_activos = Usuario.objects.filter(
activo=True,
edad__between=(18, 35)
) Ejemplo 5: Filtrado con condiciones OR Cuando necesitas aplicar condiciones con el operador OR (es decir, al menos una de las condiciones debe cumplirse), debes usar el objeto Q en Django.
from django.db.models import Q
# El operador Q permite combinar condiciones usando los operadores lógicos como AND (&) y OR (|).
# En este caso, estamos filtrando usuarios cuya edad es mayor o igual a 18,
# o bien aquellos que son empleados (es_empleado=True).
usuarios_especiales = Usuario.objects.filter(
Q(edad__gte=18) | Q(es_empleado=True)
)
# Aquí, se aplica un filtro usando el operador OR para obtener estudiantes
# que sean mayores o iguales a 18 años o cuyo promedio sea mayor a 9.0.
estudiantes_complejos = Estudiante.objects.filter(
Q(edad__gte=18) | Q(promedio__gt=9.0)
) .objects.all().count() es un método de QuerySet en Django que devuelve el número total de registros en una tabla asociada al modelo.
Este método ejecuta una consulta SQL para contar todas las filas de la tabla y devuelve un número entero.
Ejemplo 1: Contar total de estudiantes
total_estudiantes = Estudiante.objects.all().count() Ejemplo 2: Contar estudiantes por condición
estudiantes_mayores_count = Estudiante.objects.filter(edad__gte=18).count() __gte: Se utiliza para filtrar registros mayores o iguales a un valor dado.
Ejemplo: edad__gte=18 devolvería registros donde la edad es mayor o igual a 18 años.
__lte: Se usa para filtrar registros menores o iguales a un valor dado.
Ejemplo: edad__lte=18 devolvería registros donde la edad es menor o igual a 18 años.
Ejemplo 3: Contar estudiantes por curso
count_matematicas = Estudiante.objects.filter(curso='Matemáticas').count() .objects.all().select_related() es un método de QuerySet en Django que optimiza las consultas cuando hay relaciones de clave foránea.
Utiliza un solo JOIN SQL para recuperar los objetos relacionados, reduciendo el número de consultas a la base de datos y mejorando el rendimiento al acceder a datos relacionados.
Ejemplo 1: Consultar cursos con estudiantes relacionados
cursos_con_estudiantes = Curso.objects.select_related('estudiantes') Ejemplo 2: Consulta con múltiples relaciones
detalles_curso = Curso.objects.select_related('estudiantes__curso') Ejemplo 3: Prefetch relacionado
cursos_detallados = Curso.objects.prefetch_related('estudiantes') .objects.get() es un método de QuerySet en Django que se utiliza para obtener un único registro que coincida con los criterios especificados.
Si se encuentran múltiples registros que coinciden, o si no se encuentra ninguno, se lanzará una excepción (MultipleObjectsReturned o DoesNotExist).
Ejemplo 1: Obtener estudiante por ID
estudiante = Estudiante.objects.get(id=1) Ejemplo 2: Obtener por condición única
estudiante_juan = Estudiante.objects.get(nombre='Juan') Ejemplo 3: Obtener con múltiples condiciones
estudiante_especifico = Estudiante.objects.get(
nombre='María',
curso='Matemáticas'
) .objects.get().only() es un método en Django que permite recuperar un único registro y limitar los campos que se cargan en la consulta.
Esto optimiza el rendimiento al evitar la carga de columnas innecesarias.
Se utiliza junto con .get() para obtener un único objeto, pero solo con los campos especificados.
Ejemplo 1: Seleccionar solo nombre y edad
estudiantes_lite = Estudiante.objects.only('nombre', 'edad') Ejemplo 2: Usar en iteración
for estudiante in estudiantes_lite:
print(f"{estudiante.nombre} - {estudiante.edad}") Ejemplo 3: Consulta con condición
estudiantes_select = Estudiante.objects.filter(
activo=True
).only('nombre', 'promedio') .objects.get().defer() es un método en Django que permite recuperar un único registro y excluir ciertos campos de la consulta, cargando solo los campos que no se han diferido.
Es útil cuando necesitas optimizar la consulta evitando la carga de columnas específicas que no se utilizarán.
Ejemplo 1: Defer campo promedio
estudiantes_sin_promedio = Estudiante.objects.defer('promedio') Ejemplo 2: Defer múltiples campos
estudiantes_basico = Estudiante.objects.defer('promedio', 'curso') Ejemplo 3: Defer con filtro
estudiantes_activos_basico = Estudiante.objects.filter(
activo=True
).defer('promedio') Permite filtrar los registros excluyendo aquellos que coincidan con las condiciones especificadas. Es lo opuesto a .filter().
Ejemplo: Obtener todos los estudiantes cuyo promedio no sea mayor a 7
estudiantes = Estudiante.objects.exclude(promedio__gt=7)
# Excluir para obtener todos los usuarios activos
usuarios_no_activos = Usuario.objects.exclude(activo=True) Permite ordenar los resultados según un campo específico. Puedes usar - para invertir el orden.
Ejemplo: Ordenar los usuarios por edad descendente
usuarios = Usuario.objects.order_by('-edad') Ejemplos:
# Ordenar por un campo en orden ascendente (por defecto)
estudiantes_ordenados = Estudiante.objects.order_by('edad')
# Ordenar por un campo en orden descendente
usuarios_desc = Usuario.objects.order_by('-edad')
# Ordenación múltiple: primero por edad, luego por nombre
usuarios_multiples = Usuario.objects.order_by('edad', 'nombre')
# Ordenar por un campo en orden descendente (edad) y luego ascendente (nombre)
usuarios_ordenados = Usuario.objects.order_by('-edad', 'nombre') Elimina los registros duplicados de los resultados de la consulta.
Ejemplo: Obtener categorías únicas de productos
categorias = Producto.objects.values('categoria').distinct() Permite obtener un diccionario de los campos especificados en lugar de instancias del modelo.
Ejemplo: Obtener solo los nombres y correos de los usuarios
usuarios = Usuario.objects.values('nombre', 'email') Similar a .values(), pero devuelve una lista de tuplas en lugar de diccionarios.
Ejemplo: Obtener una lista de tuplas con nombre y edad de los usuarios
usuarios = Usuario.objects.values_list('nombre', 'edad') Permite realizar cálculos agregados como sum(), count(), Max, Min, avg() sobre un conjunto de resultados.
Ejemplo 1: Obtener el promedio de edad de todos los usuarios
from django.db.models import Avg, Max, Min, Sum, Count
# Calcular el promedio de edad
promedio_edad = Usuario.objects.aggregate(Avg('edad'))
# Realizar múltiples agregaciones
estadisticas = Usuario.objects.aggregate(
promedio_edad=Avg('edad'), # Promedio de edad
edad_maxima=Max('edad'), # Edad máxima
total_usuarios=Count('id') # Total de usuarios
) Ejemplo 1: Promedio de edad
edad_promedio = Usuario.objects.aggregate(Avg('edad')) Ejemplo 2: Suma total de productos
total_productos = Producto.objects.aggregate(
total_stock=Sum('stock')
) Ejemplo 3: Precio máximo y mínimo
precios_producto = Producto.objects.aggregate(
precio_max=Max('precio'),
precio_min=Min('precio')
) Permite agregar información adicional a cada objeto, como un valor calculado.
Ejemplo: Obtener el número de productos por cada pedido
from django.db.models import Count
pedidos = Pedido.objects.annotate(num_productos=Count('productos')) Obtienen el primer o último registro de una consulta.
Ejemplo: Obtener el primer y el último usuario
primer_usuario = Usuario.objects.first() # Obtiene el primer usuario
ultimo_usuario = Usuario.objects.last() # Obtiene el último usuario En Django, puedes realizar consultas sobre relaciones entre modelos, como relaciones de clave foránea (ForeignKey) o relaciones muchos a muchos (ManyToMany).
En este caso, algunos ejemplos de cómo trabajar con estas relaciones.
Ejemplo 1: Consultas con relaciones de clave foránea (ForeignKey)
pedidos_usuario = Pedido.objects.filter(usuario__nombre='Juan') Ejemplo 2: Consultas con relaciones many-to-many
productos_pedido = Producto.objects.filter(pedido__usuario__nombre='Maria') Ejemplo 3: **Subconsultas
from django.db.models import Subquery, OuterRef
usuarios_con_pedidos = Usuario.objects.filter(
id__in=Pedido.objects.filter(
total__gt=100
).values('usuario')
) Para limitar la cantidad de resultados obtenidos en una consulta, puedes usar la notación de corte ([:n]), donde n es el número máximo de registros que deseas obtener.
Ejemplo 1: Obtener los 5 primeros usuarios
top_5_usuarios = Usuario.objects.all()[:5] Ejemplo 2: Obtener los últimos 5 usuarios (ordenados por fecha de creación)
ultimos_5_usuarios = Usuario.objects.all().order_by('-fecha_creacion')[:5] Ejemplo 3: Limitar el número de productos en stock
productos_en_stock = Producto.objects.filter(stock__gt=0)[:10] En Django, los modelos relacionados se pueden acceder de forma sencilla usando los métodos que Django genera automáticamente para las relaciones de clave foránea o ManyToMany.
Ejemplo 1: Acceder a registros relacionados
Cuando se tiene una relación ForeignKey, Django crea automáticamente un manager relacionado para acceder a los objetos relacionados.
class Pedido(models.Model):
usuario = models.ForeignKey(Usuario, on_delete=models.CASCADE)
# Obtener todos los pedidos de un usuario
pedidos_usuario = usuario.pedido_set.all() Ejemplo 2: Filtrar registros relacionados
Se pueden aplicar filtros a través de las relaciones utilizando __ para acceder a los campos de los modelos relacionados.
pedidos_filtrados = Pedido.objects.filter(usuario__edad__gte=18) En este caso, estamos filtrando los pedidos para obtener solo aquellos que pertenecen a usuarios con una edad de 18 años o más.