Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

333
Vistas
Django: anotar una agregación de anotaciones en objetos relacionados

Tengo tres modelos:

 class BaseModel(Model): deleted = BooleanField(default=False) class Document(BaseModel): def total_price() return DocumentLine.objects.filter( section__in=self.sections.filter(deleted=False), deleted=False, ).total_price() class Section(BaseModel): document = ForeignKey(Document, on_delete=CASCADE, related_name='sections') class LineQuerySet(QuerySet): def with_total_price(self): total_price = F('quantity') * F('price') return self.annotate( total_price=ExpressionWrapper(total_price, output_field=DecimalField()) ) def total_price(self): return self.with_total_prices().aggregate( Sum('total_price', output_field=DecimalField()) )['total_price__sum'] or Decimal(0.0) class Line(BaseModel): objects = LineQuerySet.as_manager() section = ForeignKey(Section, on_delete=CASCADE, related_name='lines') price = DecimalField() quantity = DecimalField()

Como puede ver en LineQuerySet , hay un método que anotará el conjunto de consultas con el precio total de cada línea, según el precio y la cantidad.

Ahora puedo obtener fácilmente el precio total de un documento completo haciendo algo como esto (tenga en cuenta que las líneas y secciones con deleted=True se ignoran):

 document = Document.objects.get(pk=1) total_price = document.total_price()

Sin embargo, ahora me gustaría generar un conjunto de consultas de varios documentos y anotarlo con el total price de cada documento. Probé una combinación de anotaciones, agregados, haciendo uso de prefetch_related (usando Prefetch) y OuterRef, pero parece que no puedo obtener el resultado que quiero sin que arroje un error.

¿Hay alguna forma de realizar esta operación en un conjunto de consultas, haciendo posible filtrar u ordenar por este campo total_price ?

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Puedes anotar con:

 from django.db.models import F, Sum Document.objects.filter( deleted=False, sections__deleted=False, section__lines__deleted=False ).annotate( total_price=Sum(F('sections__lines__price')*F('sections__lines__quantity')) )

Cada Document que surja de este conjunto de consultas tendrá un atributo .total_price que es la suma del precio por la cantidad de todas las líneas relacionadas de todas las secciones relacionadas de ese Document .

Una alternativa es trabajar con una expresión Subquery [Django-doc] para determinar la suma, así:

 from django.db.models import F, OuterRef, Subquery , Sum Document.objects.annotate( total_price= Subquery( Line.objects.values( document_id=F('section__document_id') ).filter( deleted=False, section__deleted=False, document__deleted=False ).annotate( total_price=Sum(F('price') * F('quantity')) ).order_by('document_id').filter(document_id=OuterRef('pk')).values('total_price')[:1] ) )
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda