Reputation: 1121
Hi i could order by < 2 in ORM my only idea is:
players = GamePlayer.objects.raw('SELECT * FROM `Farmer_gameplayer` WHERE (`Farmer_gameplayer`.`game_id` = %d) ORDER BY `turn` < %d' % (game.pk, game.turn))
I'd like to order this:
players = GamePlayer.objects.filter(game=game) ORDER BY `turn` < 2
Upvotes: 4
Views: 2517
Reputation: 55448
Note: You can probably adapt your application to use ORDER BY turn
, as qualitatively the result set isn't very different from ORDER by turn < 2
. You'll see a difference only in that ORDER BY turn
would alter the sort of all rows depending on their turn
column, while ORDER BY turn < 2
sorts by the boolean expression turn < 2
which won't reorder all rows beyond that.
Below I present how you can order a Django queryset using an expression, e.g. turn < 2
Annotate with an expression, then order by it:
The idea is to annotate a field called turn_is_less_than_2
that goes either True or False, then order by it. The said annotation will be representing the expression turn < 2
that you want to order by later on (ORDER BY turn < 2
)
from django.db.models import Case, When, BooleanField
GamePlayer.objects.filter(game=game).annotate(turn_is_less_than_2=Case(
When(turn__lt=2, then=True),
default=False,
output_field=BooleanField()
)).order_by('turn_is_less_than_2')
# or order_by('-turn_is_less_than_2') for DESC order instead of ASC
Breaking it down to explain:
First I'm just taking your query
GamePlayer.objects.filter(game=game)
Then what I do is annotate it with a field turn_is_less_than_2
that is True
if turn < 2
, and False
otherwise
GamePlayer.objects.filter(game=game).annotate(turn_is_less_than_2=...)
Then when we have annotated that filtered queryset, we can now order_by that field:
GamePlayer.objects.filter(game=game).annotate(...).order_by('turn_is_less_than_2')
Upvotes: 4