[Django]-Complex django query including one-to-one models

4๐Ÿ‘

โœ…

Well if you write .exclude('reputation' < 200), then Python will first evaluate 'reputation' < 200 which will โ€“ in Python 3.x โ€“ fail to compare, and in Python-2.x return False, then you pass that boolean to a exclude.

But note that you never filter on the reputation at all. It is only a boolean (at best case), you pass to the filter.

You perform comparisons in Django with the parameter name: you use the __lt suffix to denote โ€œless thanโ€œ.

Another thing is that you query on the User, but the reputation is stored in UserProfile, you thus need to follow the reverse foreign key (this reverse relation is for filter profile, and you access it again by using two consecutive underscores).

So we can solve the exclude part with:

(User.objects.filter(is_online=True)
                        .order_by('profile__reputation')
                        .exclude(profile__reputation__lt=200))

Note that if you exclude vlaues below 200, this is basically the same as filtering for values equal to and larger than 200, so we can move this to the filter section:

(User.objects.filter(is_online=True, profile__reputation__gte=200)
                        .order_by('profile__reputation'))

4๐Ÿ‘

The query can be improved like the following:

queryset = User.objects.filter(is_online=True,profile__reputation__gte=200)
           .order_by('profile__reputation')
๐Ÿ‘คLemayzeur

3๐Ÿ‘

The query would probably be

qs = User.objects.filter(is_online=True, profile__reputation__gte=200)
qs = qs.order_by('profile__reputation')

But note that this will not be very performant for big tables as the sorting is done on the other table.

I suggest switching the base table to improve speed:

qs = UserProfile.objects.filter(user__is_online=True, reputation__gte=200)
qs = qs.order_by('reputation')
๐Ÿ‘คRalf

Leave a comment