Cómo dominar los conjuntos de consultas de Django: una guía completa con ejemplos prácticos

Mastering Django QuerySets: A Comprehensive Guide with Practical Examples

Table of Contents

    Al trabajar con Django, comprender los QuerySets es crucial para interactuar de manera eficiente con su base de datos. En este tutorial, lo guiaré a través de los detalles de los QuerySets utilizando un modelo de contacto simple. A lo largo del camino, explicaré qué hace cada comando, por qué es útil y cómo puede aplicarlo a situaciones del mundo real. Si recién está comenzando con Django o está buscando mejorar sus habilidades, está en el lugar correcto.

    Preparando el escenario: el modelo de contacto

    Comencemos creando un pequeño modelo de contacto. Imagina que estás creando una libreta de direcciones en la que cada contacto tiene un nombre, un apellido y una dirección de correo electrónico. Así es como se ve en Django:

     from django.db import models class Contact(models.Model): first_name = models.CharField(max_length=50) last_name = models.CharField(max_length=50) email = models.EmailField(unique=True) def __str__(self): return f"{self.first_name} {self.last_name}"

    Este modelo es bastante sencillo. Los campos first_name y last_name son CharFields con una longitud máxima de 50 caracteres, mientras que el campo de correo electrónico es único, lo que garantiza que no haya direcciones de correo electrónico duplicadas. El método __str__ devuelve una bonita representación del contacto, perfecta para depurar o mostrar datos.

    Ejecute sus migraciones para aplicar este modelo a su base de datos:

     python manage.py makemigrations python manage.py migrate

    Con el modelo listo, profundicemos en QuerySets.

    ¿Qué es un QuerySet?

    Un QuerySet es básicamente una colección de consultas de base de datos. Piense en ello como una forma de recuperar, filtrar y manipular datos de su base de datos. La belleza de los QuerySets es que son perezosos, lo que significa que no llegan a la base de datos hasta que los evalúe explícitamente. Esto los hace potentes y eficientes.

    Completemos nuestra base de datos con algunos datos de muestra antes de explorar QuerySets.

    Agregar datos de muestra

    Abra el shell de Django para crear algunos contactos:

     python manage.py shell

    Dentro de la concha:

     from app.models import Contact Contact.objects.create(first_name="Alice", last_name="Smith", email="alice@example.com") Contact.objects.create(first_name="Bob", last_name="Jones", email="bob@example.com") Contact.objects.create(first_name="Charlie", last_name="Brown", email="charlie@example.com") Contact.objects.create(first_name="Diana", last_name="Prince", email="diana@example.com")

    Ahora tenemos algunos datos con los que trabajar. Analicemos QuerySets y veamos qué podemos hacer.

    Recuperando todos los registros

    El QuerySet más simple es Contact.objects.all(). Este recupera todos los registros de la tabla Contact.

     contacts = Contact.objects.all() print(contacts)

    Notarás que no obtiene los datos inmediatamente, sino que simplemente prepara la consulta. Esta es una característica excelente de QuerySets porque evita accesos innecesarios a la base de datos hasta que necesitas los datos.

    ¿Por qué usarlo?

    Si desea ver todo lo que hay en su tabla, all() es la opción ideal. También es el punto de partida para encadenar otros comandos, que veremos a continuación.

    Contando récords

    ¿Quieres saber cuántos contactos tienes? Utiliza .count().

     count = Contact.objects.all().count() print(f"Total Contacts: {count}")

    Esto envía una consulta SELECT COUNT(*) a la base de datos, lo que es más rápido que cargar todos los objetos y contarlos en Python.

    ¿Por qué usarlo?

    Cuando necesita un resumen rápido de sus datos, contar registros es invaluable.

    Comprobando la existencia

    Si solo desea saber si existe algún registro, .exists() es su amigo.

     exists = Contact.objects.all().exists() print(f"Contacts Exist: {exists}")

    Esto es mucho más rápido que obtener todos los registros, ya que detiene la búsqueda tan pronto como encuentra la primera coincidencia.

    ¿Por qué usarlo?

    Perfecto para escenarios como la lógica condicional: si hay datos, haz una cosa; si no, haz otra.

    Recuperación de registros específicos

    A veces, sabes exactamente lo que estás buscando. Usa .get() para recuperar un solo registro mediante una condición específica:

     alice = Contact.objects.get(email="alice@example.com") print(f"Found Contact: {alice}")

    La captura

    • Si no coincide ningún registro, se genera una excepción DoesNotExist.
    • Si coinciden varios registros, se genera un error una excepción MultipleObjectsReturned.

    Filtrado de datos

    ¿Qué sucede si desea conocer todos los contactos con un apellido específico? Ahí es donde entra en juego .filter().

     smith_contacts = Contact.objects.filter(last_name="Smith") print(smith_contacts)

    Esto crea un QuerySet de todos los registros coincidentes. Puede utilizar varias búsquedas de campo para refinar su búsqueda:

    • icontains : Búsqueda sin distinción entre mayúsculas y minúsculas.
    • startswith : Coincide con el inicio de una cadena.
    • exacto : coincide con el valor exacto.

    Por ejemplo:

     emails_with_example = Contact.objects.filter(email__icontains="example.com")

    ¿Por qué usarlo?

    El filtrado es una de las operaciones más comunes en cualquier aplicación basada en bases de datos. Le permite centrarse en los datos que necesita.

    Excluyendo datos

    ¿Quieres todo excepto un conjunto específico de registros? Usa .exclude():

     non_smith_contacts = Contact.objects.exclude(last_name="Smith") print(non_smith_contacts)

    Ordenar resultados

    Ordenar sus datos es sencillo con .order_by().

     ordered_contacts = Contact.objects.all().order_by("first_name") print(ordered_contacts)

    Para ordenar en orden descendente, anteponga el campo con un - :

     descending_contacts = Contact.objects.all().order_by("-last_name")

    Agregaciones

    Si trabaja con datos numéricos, Django tiene funciones de agregación integradas como Count , Sum , Avg , Max y Min . Contemos cuántos apellidos únicos tenemos:

     from django.db.models import Count unique_last_names = Contact.objects.values("last_name").distinct().count() print(f"Unique Last Names: {unique_last_names}")

    Anotación de conjuntos de consultas

    Las anotaciones le permiten agregar campos calculados a su QuerySet. Por ejemplo, es posible que desee crear un campo full_name de forma dinámica:

     from django.db.models import Value from django.db.models.functions import Concat contacts = Contact.objects.annotate( full_name=Concat('first_name', Value(' '), 'last_name') ) for contact in contacts: print(contact.full_name)

    Resultados del corte

    ¿Necesita solo un subconjunto de sus datos? Utilice la segmentación:

     top_two_contacts = Contact.objects.all()[:2]

    SQL sin procesar

    Si tienes curiosidad sobre lo que Django hace en segundo plano, puedes inspeccionar el SQL sin procesar:

     print(Contact.objects.all().query)

    Conclusión

    Los QuerySets de Django son increíblemente potentes y dominarlos es un punto de inflexión para trabajar con datos en sus proyectos. Ya sea que esté filtrando registros, contando filas o realizando consultas complejas, los QuerySets le brindan las herramientas que necesita para realizar el trabajo de manera eficiente.

    Si comprende los conceptos básicos y se adentra en operaciones más avanzadas, podrá escribir código limpio y optimizado que aproveche al máximo el ORM de Django. Si esta guía le resultó útil, no dude en compartirla; ¡puede ser el recurso que alguien más está buscando!

    Published: 3 weeks, 5 days ago.