#28657: Strangely odd behaviour when ordering QuerySet by BooleanField.
-------------------------------------+-------------------------------------
     Reporter:  Leonardo Arroyo      |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:  Database layer       |                  Version:  1.11
  (models, ORM)                      |
     Severity:  Normal               |               Resolution:
     Keywords:  queryset, boolean,   |             Triage Stage:
  order, ordering                    |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------
Description changed by Leonardo Arroyo:

Old description:

> I have recently encountered problems with duplicated results in
> pagination and trying to pin down the problem this seems to be a problem
> in the Django queryset. I'll attempt to explain the problem. Take a look
> at the following Queryset:
>

> {{{
> >>> p = Project.objects.all().order_by("closed")
> >>> p
> <QuerySet [<Project: Campanha de Incentivo - Alimentando a Solidariedade
> (Outubro)>, <Project: Campanha de Incentivo - Projeto Fora das 4
> Paredes>, <Project: projeto luciele>, <Project: Campanha de Incentivo -
> Menos é Mais>, <Project: Campanha de Incentivo - Projeto Conviver>,
> <Project: Campanha de Incentivo - Aula de Música>, <Project: RPINCLUSÃO -
> Informações, Acessibilidade e Inclusão>, <Project: Ong ong>, <Project:
> Campanha de Incentivo - Projeto Alimentando Vidas>, <Project: Bola na
> Rede>, <Project: Campanha de Incentivo - Projeto Bolas de Pelos>,
> <Project: Mãos Solidárias>, <Project: Campanha de Incentivo - GRUPO DE
> ATITUDE SOCIAL - Moradores de Rua>, <Project: APAE pede Socorro>,
> <Project: Campanha de Incentivo - Anjos da Madrugada>, <Project: Pintura
> de Casas Emergenciais com o TETO - São Paulo>, <Project: Campanha de
> Incentivo - Aos Olhos do Pai>, <Project: Legião da Boa Vontade>,
> <Project: Campanha de Incentivo - Você é a gota que faltava, Doe
> Sangue!>, <Project: Campanha de Incentivo - Sonhar com Esperança>,
> '...(remaining elements truncated)...']>
> }}}
>

> The 'closed' field here is a Boolean. Everything seems to be correct
> except for this:
>
> {{{
> >>> p[0]
> <Project: Campanha de Incentivo - Anjos da Madrugada>
> >>> p[1]
> <Project: Bola na Rede>
> }}}
>

> When I get items from the queryset, they don't match the queryset
> __repr__ order. What is even weirder is that neither the __repr__ order
> nor the __getitem__ order matches the PostgreSQL query.
>

> {{{
> >>> print(p.query)
> SELECT "ovp_projects_project"."id", "ovp_projects_project"."image_id",
> "ovp_projects_project"."address_id", "ovp_projects_project"."owner_id",
> "ovp_projects_project"."organization_id", "ovp_projects_project"."name",
> "ovp_projects_project"."slug", "ovp_projects_project"."published",
> "ovp_projects_project"."highlighted",
> "ovp_projects_project"."applied_count",
> "ovp_projects_project"."max_applies",
> "ovp_projects_project"."max_applies_from_roles",
> "ovp_projects_project"."public_project",
> "ovp_projects_project"."minimum_age",
> "ovp_projects_project"."hidden_address",
> "ovp_projects_project"."crowdfunding",
> "ovp_projects_project"."published_date", "ovp_projects_project"."closed",
> "ovp_projects_project"."closed_date", "ovp_projects_project"."deleted",
> "ovp_projects_project"."deleted_date",
> "ovp_projects_project"."created_date",
> "ovp_projects_project"."modified_date", "ovp_projects_project"."details",
> "ovp_projects_project"."description" FROM "ovp_projects_project" ORDER BY
> "ovp_projects_project"."closed" ASC
> }}}
>

> When hitting the database with such query, only removing a couple of
> fields to make it easier to read, this is what I get:
> [[Image(blob:https://imgur.com/c888a1a0-cf27-44f4-b3d5-3a91174eb9ab)]]
>
> These are 3 different orders. Now, there's one little thing I can do to
> fix the QuerySet, which is iterating over it.
>
> {{{
> >>> for x in p:
> ...   print(x.pk)
> ...
> 81
> 74
> 75
> 91
> 83
> 61
> (...)
> }}}
>

> Suddenly the queryset now matches the result from my PostgreSQL query and
> everything is now correct.
>
> {{{
> >>> p
> <QuerySet [<Project: Pintura de Casas Emergenciais com o TETO - São
> Paulo>, <Project: Campanha de Incentivo - Anjos da Madrugada>, <Project:
> Ong ong>, <Project: projeto luciele>, <Project: Campanha de Incentivo -
> Projeto Alimentando Vidas>, <Project: Campanha de Incentivo - Menos é
> Mais>, <Project: Campanha de Incentivo - Alimentando a Solidariedade
> (Outubro)>, <Project: Campanha de Incentivo - Aula de Música>, <Project:
> Campanha de Incentivo - Projeto Fora das 4 Paredes>, <Project: Campanha
> de Incentivo - Padoca Artesanal>, <Project: Campanha de Incentivo -
> EmpoderA>, <Project: Campanha de Incentivo - Moto Sopa>, <Project:
> Campanha Incentivo - Projeto Vale Jequitinhonha>, <Project: Campanha de
> Incentivo - Eternas Crianças>, <Project: Campanha de Incentivo - Festa de
> Natal>, <Project: Treinador voluntário de futebol - Águias Livres>,
> <Project: Fundação Gol de Letra - Faça parte deste time!>, <Project:
> Campanha de Incentivo - Ganhando Almas>, <Project: Campanha de
> Incentivo - Acolchoados de Ponto Cruz e Patchwork>, <Project: Campanha de
> Incentivo - Show de Encantamento Solidário>, '...(remaining elements
> truncated)...']>
> >>> p[0]
> <Project: Pintura de Casas Emergenciais com o TETO - São Paulo>
> >>> p[1]
> <Project: Campanha de Incentivo - Anjos da Madrugada>
> }}}
>

> I'm trying to find out where the problem is really happening but I have
> limited knowledge about django ORM internals, so I haven't gotten that
> far yet. Currently I'm hacking around it by iterating over the queryset
> before paginating it and passing it to my view.
>
> Things get even weirder if I try to order by 2 boolean fields, with
> issues such as:
>
> {{{
> >>> p = Project.objects.all().order_by("closed", "-highlighted")
> >>> p
> <QuerySet [<Project: Campanha Incentivo - Projeto Vale Jequitinhonha>,
> <Project: Campanha de Incentivo - Alimentando a Solidariedade (Outubro)>,
> <Project: Campanha de Incentivo - Festa do Dia Das Crianças>, <Project:
> Campanha de Incentivo - Cartas para o "Papai Noel">, <Project: Pintura de
> Casas Emergenciais com o TETO - São Paulo>, <Project: Campanha de
> Incentivo - Padoca Artesanal>, <Project: Campanha de Incentivo -
> EmpoderA>, <Project: Construção de Casas Emergenciais com o TETO - São
> Paulo - Estrutura e entrega  da casa>, <Project: Campanha de Incentivo -
> Doação de Brinquedos>, <Project: Campanha de Incentivo - Pequena ajuda,
> grande transformação>, <Project: Campanha de Incentivo - Aula de Música>,
> <Project: Campanha de Incentivo - Aos Olhos do Pai>, <Project: APAE pede
> Socorro>, <Project: Campanha de Incentivo - GRUPO DE ATITUDE SOCIAL -
> Moradores de Rua>, <Project: Mãos Solidárias>, <Project: Campanha de
> Incentivo - Projeto Bolas de Pelos>, <Project: Campanha de Incentivo -
> Projeto Conviver>, <Project: Bola na Rede>, <Project: Campanha de
> Incentivo - Você é a gota que faltava, Doe Sangue!>, <Project: projeto
> luciele>, '...(remaining elements truncated)...']>
> >>> p[0], p[0].pk
> (<Project: Pintura de Casas Emergenciais com o TETO - São Paulo>, 81)
> >>> p[1], p[1].pk
> (<Project: Pintura de Casas Emergenciais com o TETO - São Paulo>, 81)
> }}}

New description:

 I have recently encountered problems with duplicated results in pagination
 and trying to pin down the problem this seems to be a problem in the
 Django queryset. I'll attempt to explain the problem. Take a look at the
 following Queryset:


 {{{
 >>> p = Project.objects.all().order_by("closed")
 >>> p
 <QuerySet [<Project: Campanha de Incentivo - Alimentando a Solidariedade
 (Outubro)>, <Project: Campanha de Incentivo - Projeto Fora das 4 Paredes>,
 <Project: projeto luciele>, <Project: Campanha de Incentivo - Menos é
 Mais>, <Project: Campanha de Incentivo - Projeto Conviver>, <Project:
 Campanha de Incentivo - Aula de Música>, <Project: RPINCLUSÃO -
 Informações, Acessibilidade e Inclusão>, <Project: Ong ong>, <Project:
 Campanha de Incentivo - Projeto Alimentando Vidas>, <Project: Bola na
 Rede>, <Project: Campanha de Incentivo - Projeto Bolas de Pelos>,
 <Project: Mãos Solidárias>, <Project: Campanha de Incentivo - GRUPO DE
 ATITUDE SOCIAL - Moradores de Rua>, <Project: APAE pede Socorro>,
 <Project: Campanha de Incentivo - Anjos da Madrugada>, <Project: Pintura
 de Casas Emergenciais com o TETO - São Paulo>, <Project: Campanha de
 Incentivo - Aos Olhos do Pai>, <Project: Legião da Boa Vontade>, <Project:
 Campanha de Incentivo - Você é a gota que faltava, Doe Sangue!>, <Project:
 Campanha de Incentivo - Sonhar com Esperança>, '...(remaining elements
 truncated)...']>
 }}}


 The 'closed' field here is a Boolean. Everything seems to be correct
 except for this:

 {{{
 >>> p[0]
 <Project: Campanha de Incentivo - Anjos da Madrugada>
 >>> p[1]
 <Project: Bola na Rede>
 }}}


 When I get items from the queryset, they don't match the queryset __repr__
 order. What is even weirder is that neither the __repr__ order nor the
 __getitem__ order matches the PostgreSQL query.


 {{{
 >>> print(p.query)
 SELECT "ovp_projects_project"."id", "ovp_projects_project"."image_id",
 "ovp_projects_project"."address_id", "ovp_projects_project"."owner_id",
 "ovp_projects_project"."organization_id", "ovp_projects_project"."name",
 "ovp_projects_project"."slug", "ovp_projects_project"."published",
 "ovp_projects_project"."highlighted",
 "ovp_projects_project"."applied_count",
 "ovp_projects_project"."max_applies",
 "ovp_projects_project"."max_applies_from_roles",
 "ovp_projects_project"."public_project",
 "ovp_projects_project"."minimum_age",
 "ovp_projects_project"."hidden_address",
 "ovp_projects_project"."crowdfunding",
 "ovp_projects_project"."published_date", "ovp_projects_project"."closed",
 "ovp_projects_project"."closed_date", "ovp_projects_project"."deleted",
 "ovp_projects_project"."deleted_date",
 "ovp_projects_project"."created_date",
 "ovp_projects_project"."modified_date", "ovp_projects_project"."details",
 "ovp_projects_project"."description" FROM "ovp_projects_project" ORDER BY
 "ovp_projects_project"."closed" ASC
 }}}


 When hitting the database with such query, only removing a couple of
 fields to make it easier to read, this is what I get:
 [[Image(https://code.djangoproject.com/attachment/ticket/28657/django-
 boolean-bug.png)]]

 These are 3 different orders. Now, there's one little thing I can do to
 fix the QuerySet, which is iterating over it.

 {{{
 >>> for x in p:
 ...   print(x.pk)
 ...
 81
 74
 75
 91
 83
 61
 (...)
 }}}


 Suddenly the queryset now matches the result from my PostgreSQL query and
 everything is now correct.

 {{{
 >>> p
 <QuerySet [<Project: Pintura de Casas Emergenciais com o TETO - São
 Paulo>, <Project: Campanha de Incentivo - Anjos da Madrugada>, <Project:
 Ong ong>, <Project: projeto luciele>, <Project: Campanha de Incentivo -
 Projeto Alimentando Vidas>, <Project: Campanha de Incentivo - Menos é
 Mais>, <Project: Campanha de Incentivo - Alimentando a Solidariedade
 (Outubro)>, <Project: Campanha de Incentivo - Aula de Música>, <Project:
 Campanha de Incentivo - Projeto Fora das 4 Paredes>, <Project: Campanha
 de Incentivo - Padoca Artesanal>, <Project: Campanha de Incentivo -
 EmpoderA>, <Project: Campanha de Incentivo - Moto Sopa>, <Project:
 Campanha Incentivo - Projeto Vale Jequitinhonha>, <Project: Campanha de
 Incentivo - Eternas Crianças>, <Project: Campanha de Incentivo - Festa de
 Natal>, <Project: Treinador voluntário de futebol - Águias Livres>,
 <Project: Fundação Gol de Letra - Faça parte deste time!>, <Project:
 Campanha de Incentivo - Ganhando Almas>, <Project: Campanha de
 Incentivo - Acolchoados de Ponto Cruz e Patchwork>, <Project: Campanha de
 Incentivo - Show de Encantamento Solidário>, '...(remaining elements
 truncated)...']>
 >>> p[0]
 <Project: Pintura de Casas Emergenciais com o TETO - São Paulo>
 >>> p[1]
 <Project: Campanha de Incentivo - Anjos da Madrugada>
 }}}


 I'm trying to find out where the problem is really happening but I have
 limited knowledge about django ORM internals, so I haven't gotten that far
 yet. Currently I'm hacking around it by iterating over the queryset before
 paginating it and passing it to my view.

 Things get even weirder if I try to order by 2 boolean fields, with issues
 such as:

 {{{
 >>> p = Project.objects.all().order_by("closed", "-highlighted")
 >>> p
 <QuerySet [<Project: Campanha Incentivo - Projeto Vale Jequitinhonha>,
 <Project: Campanha de Incentivo - Alimentando a Solidariedade (Outubro)>,
 <Project: Campanha de Incentivo - Festa do Dia Das Crianças>, <Project:
 Campanha de Incentivo - Cartas para o "Papai Noel">, <Project: Pintura de
 Casas Emergenciais com o TETO - São Paulo>, <Project: Campanha de
 Incentivo - Padoca Artesanal>, <Project: Campanha de Incentivo -
 EmpoderA>, <Project: Construção de Casas Emergenciais com o TETO - São
 Paulo - Estrutura e entrega  da casa>, <Project: Campanha de Incentivo -
 Doação de Brinquedos>, <Project: Campanha de Incentivo - Pequena ajuda,
 grande transformação>, <Project: Campanha de Incentivo - Aula de Música>,
 <Project: Campanha de Incentivo - Aos Olhos do Pai>, <Project: APAE pede
 Socorro>, <Project: Campanha de Incentivo - GRUPO DE ATITUDE SOCIAL -
 Moradores de Rua>, <Project: Mãos Solidárias>, <Project: Campanha de
 Incentivo - Projeto Bolas de Pelos>, <Project: Campanha de Incentivo -
 Projeto Conviver>, <Project: Bola na Rede>, <Project: Campanha de
 Incentivo - Você é a gota que faltava, Doe Sangue!>, <Project: projeto
 luciele>, '...(remaining elements truncated)...']>
 >>> p[0], p[0].pk
 (<Project: Pintura de Casas Emergenciais com o TETO - São Paulo>, 81)
 >>> p[1], p[1].pk
 (<Project: Pintura de Casas Emergenciais com o TETO - São Paulo>, 81)
 }}}

--

-- 
Ticket URL: <https://code.djangoproject.com/ticket/28657#comment:1>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/072.a7c187709a8d072c35c8faf66147fa5b%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to