Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#31581 closed Bug (invalid)

Queryset bug when using Q()? -- doubles up the counts by doing an extra join.

Reported by: Javier Buzzi Owned by: nobody
Component: Database layer (models, ORM) Version: 3.0
Severity: Normal Keywords:
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Javier Buzzi)

I ran this on all the "recent" versions of python and i see the issue on all of them. At this point, im not 100% sure if it is a problem or not, i ran across this trying to show some counts in the Admin that had some search_fields that traversed the model backwards and forwards in order to match the thing properly.

This "bug" can be seen from 1.11-3.0. Haven't checked 3.1 because i cant find it in pip.

This is my mocked models of the issue:

class ModelA(models.Model):
    somecriteria = models.CharField(max_length=50)


class ModelC(models.Model):
    unimportant = models.CharField(max_length=50)


class ModelB(models.Model):
    somerelation = models.ForeignKey(ModelA, on_delete=models.CASCADE)
    m2m = models.ManyToManyField(
        ModelC,
        through='ModelBC'
    )


class ModelBC(models.Model):
    b = models.ForeignKey(ModelB, on_delete=models.CASCADE)
    c = models.ForeignKey(ModelC, on_delete=models.CASCADE)

The "bug" is shown when i do:

queryset = ModelB.objects.select_related('a').annotate(num_c=Count('m2m__id')).values('num_c')
queryset = queryset.filter(Q(modelbc__c__unimportant='1') | Q(somerelation__somecriteria='1'))

When i do:

queryset = ModelB.objects.select_related('a').annotate(num_c=Count('m2m__id')).values('num_c')
queryset = queryset.filter(modelbc__c__unimportant='1', somerelation__somecriteria='1')

it works as expected.

My testing arena can be found here: https://gist.github.com/kingbuzzman/9fe5470e31a421aa88b2a64e5447e147 see the comments, for the way to run it.

Change History (5)

comment:1 by Javier Buzzi, 5 years ago

Summary: Queryset bug when using Q()?Queryset bug when using Q()? -- doubles up the counts by doing an extra join

comment:2 by Javier Buzzi, 5 years ago

Description: modified (diff)

comment:3 by Javier Buzzi, 5 years ago

Description: modified (diff)

comment:4 by Mariusz Felisiak, 5 years ago

Resolution: invalid
Status: newclosed
Summary: Queryset bug when using Q()? -- doubles up the counts by doing an extra joinQueryset bug when using Q()? -- doubles up the counts by doing an extra join.

These querysets are different so you cannot expect the same results:

  • Q(condition1) | Q(condition2) means "condition1 OR condition2",
  • .filter(condition1, condition2) means "condition1 AND condition2".
Last edited 5 years ago by Mariusz Felisiak (previous) (diff)

comment:5 by Javier Buzzi, 5 years ago

My apologies, i just realized my mistake. Looks like im going to have to wrap the admin filters in order for it to work correctly, and thats fine. The ORM is working as expected. Sorry to waste anyones time.

Note: See TracTickets for help on using tickets.
Back to Top