Consultas Django Concat

No se puede hacer una consulta de una @property pero puedes crear un valor personalizado concatenando

Ejemplo fullname:

from django.db.models import Value
from django.db.models.functions import Concat

Person.objects.annotate(
    fullname=Concat("fist_name", Value(" "), "last_name")
    .filter(fullname__icontains="pedro perez")
    .values_list("fullname")
) 

Consultas Django

Consultar todos los elementos de un modelo.

all_entries = Entry.objects.all()

Filtrar por uno o varios atributos, se puede filtrar por fecha(year, month, day, …), si es mayor, mayor igual (gt, gte, lt, lte, …) leer más.

Entry.objects.filter(pub_date__year=2006)

Buscar un elemento con get().

entry = Entry.objects.get(pk=1)

«Anotaciones»

  • numero de mascotas por tipo, accedes con doble barra baja __count
  • número de entradas de diferentes blogs, tomas la función de agregación (Count()) y la igualas a un nombre que gustes (number_of_entries), y con ese nombre accedes al valor que querías calcular por cada elemento.
from django.db.models import Count

qs1 = Pet.objects.values('type').annotate(Count("type"))
#[(type: fish, type__count: 354), (type: dog, type__count: 375) ...]


qs2 = Blog.objects.annotate(number_of_entries=Count('entry'))
qs2[0].name
#'primer blog'
qs2[0].number_of_entries
#40 "publicaciones del primer blog"

Consultas Django «F objects»

class Persona(models.Model):
    #...
    last_donate = models.DateTimeField()
    can_donate_on = models.DateTimeField()

filtro sencillo, personas con fechas anteriores o iguales a «ahora (now)»

from django.utils import timezone

qs = Persona.objects.filter(can_donate_on__lte=timezone.now())

Filtrar operando valores del objeto

from datetime import timedelta
from django.db.models import F


qs = Persona.objects.annotate(can_donate_on=F("last_donate") + timedelta(day=56)).

filter(can_donate_on__lt=timezone.now())

otro ejemplo con conteos y operaciones (Banco de sangre; meta de bolsas; bolsas actuales; cuantas faltan)

qs = BloodBank.objects.annotate(
    existent_amount=Count("blood_bag_set"),
    remaining=F("goal")-F("existent_amount"),
).value_list("goal", "existent_amount", "remaining")
#1500 1000 500

Operar tipos distintos

from django.db.models import ExpressionWrapper, DateTimeField

qs = Event.objects.annotate(
    ends_on=ExpressionWrapper(F("start_at")+F("duration"), 
    output_field=DateTimeField())
    )
)

Extraído de

DjangoCon 2019 – Building effective Django queries with expressions by Vanessa Barreiros – YouTube

Consultas Django Q objects

Combinar condiciones & para AND, | para OR, ~ para negación

from django.db.models import Q

Person.objects.filter(Q(
    Q(birthdate__year__range=(1981, 1996))
    | Q(birthday__year__range=(1946,1964))
    ) & ~Q(location__postal_code="NY")
)

agregar filtros dinámicamente

...
value = params["value"]
user_filter = Q(is_active=True)
if "name" in params:
    user_filter.add(Q(first_name__icontains=value) | Q(last_name__icontains=value), Q.OR)

if "job" in params:
    user_filter.add(Q(job_name__icontains=value), Q.OR)

if "email" in params:
    user_filter.add(Q(email__icontains=value), Q.OR)

qs = Person.objects.filter(user_filter)
...

Extraido de

DjangoCon 2019 – Building effective Django queries with expressions by Vanessa Barreiros – YouTube