djangodjango-modelsmany-to-manydjango-ormm2m

Django - how to retain add order when querying m2m field?


I have a CustomUser model, and a models which refer to it through a m2m relationship:

class CustomUser(AbstractUser):
   ...


class Game(models.Model):
     players = models.ManyToManyField(
        CustomUser, related_name='games',)

When I am getting the list of players, I was expecting to receive the list of players by "adding" order, however, the players always show-up ordered by 'id' of the CustomUser table

...even if CustomUser has no ordering at the model level and I didn't saw anywhere in the Django code that there was any kind of ordering in AbstractUser

user1=CustomUser.objects.get(id=1)
user2=CustomUser.objects.get(id=2)
user3=CustomUser.objects.get(id=3)

game=Game.objects.create()

game.players.add(user3)
game.players.add(user1)
game.players.add(user2)

game.players.all()

gives always user1, user2, user3

How do I do to obtain the list of m2m records in the "adding" order(user3, user1,user2) ?

I was thinking to ask to order the queryset by 'id' in the through table, but I wasn't able to figure out how to do that.

Can somebody show me how I could do that ? ... or propose me a working solution ?

Thanks in advance


Solution

  • OK, after attempting a lot of things, I found one satisfying solution, through ordering the queryset by 'id' in the through table.

    Can become handy to someone else as there not seems to be a lot of availlable knowledge on using implicit through table out there:

    class Game(models.Model):
         players = models.ManyToManyField(
            CustomUser, related_name='games',)
    
         def get_players(self):
             # need to order_by to order by the id of the through table to ensure the players are listed by order of creation in game table.
             # all other way end up to have the records ordered by user_id instead of order of joining the game
           
             return self.players.through.objects.filter(game_id=self.id).order_by('id')