how to sort by a computed value in django
-
06-09-2019 - |
Question
Hey I want to sort objects based on a computed value in django... how do I do it?
Here is an example User profile model based on stack overflow that explains my predicament:
class Profile(models.Model):
user = models.ForeignKey(User)
def get_reputation():
...
return reputation
reputation = property(get_reputation)
So, say I want to sort users by reputation. How do I do that? I know you can't just do this:
Profile.objects.order_by("-reputation")
Thanks for your help everyone :)
Solution
If you need to do the sorting in the database (because you have lots of records, and need to e.g. paginate them), the only real option is to turn reputation into a denormalized field (e.g. updated in an overridden save()
method on the model).
OTHER TIPS
Since your calculation code exists only within Python, you have to perform the sorting in Python as well:
sorted (Profile.objects.all (), key = lambda p: p.reputation)
As of Django-1.8, it is possible to sort a QuerySet using query expressions as long as the computed value can be rendered in SQL. You can also use annotations
to the model as the order_by
term.
from django.db.models import F
Profile.objects.annotate(reputation=(F('<field>') + ...)).order_by("-reputation")
Basic operations like +
, -
, *
, /
and **
can be used with F()
. In addition there are several other functions such as Count
, Avg
, Max
, ...
Links:
- Aggregation -
order_by
- Making Queries - filters can reference fields on a model
- Query Expressions - Built in Expressions
See also this SO Q&A: Order a QuerySet by aggregate field value