Search code examples
djangodjango-querysetprefetch

Filter queryset by date on prefetch_related


I need to filter a queryset by comparing dates on related objects, but the filter its ignored.

My resumed model is:

class Requerimiento(models.Model):
    nombre = models.CharField(max_length=30)
    fecha_publicacion = models.DateField(default=datetime.now)
    fecha_aprobacion = models.DateField(default=datetime.now, blank=True)
    aprobacion = models.BooleanField()
    autor = models.ForeignKey(User, null=True, blank=True)

    def __unicode__(self):
            return self.nombre

class Contexto(models.Model):
    nombre = models.CharField(max_length=30)
    requerimientos = models.ManyToManyField(Requerimiento, 
        related_name = 'contextos')

    def __unicode__(self):
            return self.nombre

class Proyecto(models.Model):
    nombre = models.CharField(max_length=30)
    cod_proyecto = models.CharField(max_length=10)
    contextos = models.ManyToManyField('Contexto', related_name = 'proyectos')
    fecha_publicacion  = models.DateField(default=datetime.now)
    autor = models.ForeignKey(User, null=True, blank=True)

And the queryset is:

queryset=Proyecto.objects.filter(pk=proyecto_id)\
    .prefetch_related('contextos')\
    .prefetch_related('contextos__requerimientos')\
    .filter(contextos__requerimientos__fecha_aprobacion__lte=F('fecha_publicacion'))

What i'm doing wrong?

EDIT

Looking with debug-toolbar i see the following with proyect id 2 selected in the following code

requerimientos = ProyectoFilter(request.GET,
    queryset=Proyecto.objects.filter(pk=proyecto_id)
    .distinct()
    .prefetch_related('contextos')
    .prefetch_related('contextos__requerimientos')
    .filter(contextos__requerimientos__fecha_aprobacion__lte=F('fecha_publicacion')))

First query:

SELECT ••• FROM "sgrs_proyecto" INNER JOIN "sgrs_proyecto_contextos" 
ON ( "sgrs_proyecto"."id" = "sgrs_proyecto_contextos"."proyecto_id" ) 
INNER JOIN "sgrs_contexto" ON ( "sgrs_proyecto_contextos"."contexto_id" =  
"sgrs_contexto"."id" ) INNER JOIN "sgrs_contexto_requerimientos" 
ON ( "sgrs_contexto"."id" = "sgrs_contexto_requerimientos"."contexto_id" ) 
INNER JOIN "sgrs_requerimiento" ON ( "sgrs_contexto_requerimientos"."requerimiento_id" = "sgrs_requerimiento"."id" ) 
WHERE ("sgrs_proyecto"."id" = 2 AND "sgrs_requerimiento"."fecha_aprobacion" 
<= "sgrs_proyecto"."fecha_publicacion")

Second query:

SELECT ••• FROM "sgrs_contexto" INNER JOIN "sgrs_proyecto_contextos" 
ON ( "sgrs_contexto"."id" = "sgrs_proyecto_contextos"."contexto_id" ) 
WHERE "sgrs_proyecto_contextos"."proyecto_id" IN (2) 
ORDER BY "sgrs_contexto"."indice_riesgo" DESC

Third query:

SELECT ••• FROM "sgrs_requerimiento" INNER JOIN "sgrs_contexto_requerimientos" 
ON ( "sgrs_requerimiento"."id" = "sgrs_contexto_requerimientos"."requerimiento_id" )
WHERE "sgrs_contexto_requerimientos"."contexto_id" IN (3, 7, 6, 4, 2, 5, 1)

The date filter is in the first query and should be in the third, is this correct? How can i get the correct filter position?

Thanks


Solution

  • OK, finally got it. I took out the filter from the queryset and make this comparison in the template.

    Just added the following:

    ...
    {% for requerimiento in contexto.requerimientos.all %}
    {% if requerimiento.fecha_aprobacion <= proyecto.fecha_publicacion %}
    ...
    

    Hope this helps others.