Question

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

Was it helpful?

Solution 2

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.

OTHER TIPS

First of all the usage of prefetch_related is not correct. See first note in https://docs.djangoproject.com/en/dev/ref/models/querysets/#prefetch-related. Second, you might want to use distinct() with queries with filters on m2m relation.

The query you have posted should give you all Proyecto objects that have at least one related Requerimiento with fecha_aprobacion less or equal than its' own fecha_aprobacion. What do you expect from the query and what do you get?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top