How to do SELECT MAX in Django?

Viewed 168212

I have a list of objects how can I run a query to give the max value of a field:

I'm using this code:

def get_best_argument(self):
    try:
        arg = self.argument_set.order_by('-rating')[0].details
    except IndexError:
        return 'no posts'
    return arg

rating is an integer

7 Answers

See this. Your code would be something like the following:

from django.db.models import Max
# Generates a "SELECT MAX..." query
Argument.objects.aggregate(Max('rating')) # {'rating__max': 5}

You can also use this on existing querysets:

from django.db.models import Max
args = Argument.objects.filter(name='foo') # or whatever arbitrary queryset
args.aggregate(Max('rating')) # {'rating__max': 5}

If you need the model instance that contains this max value, then the code you posted is probably the best way to do it:

arg = args.order_by('-rating')[0]

Note that this will error if the queryset is empty, i.e. if no arguments match the query (because the [0] part will raise an IndexError). If you want to avoid that behavior and instead simply return None in that case, use .first():

arg = args.order_by('-rating').first() # may return None

sol 01:

from .models import MyMODEL

max_rating = MyMODEL.objects.order_by('-rating').first()

sol 02:

from django.db.models import Max
from .models import MyMODEL

max_rating = MyMODEL.objects.aggregate(Max('rating'))

If you also want to get a value other than None in case the table is empty (e.g. 0), combine Max with Coalesce:

from django.db.models import Max, Value
from django.db.models.functions import Coalesce

max_rating = SomeModel.objects.aggregate(
    max_rating=Coalesce(Max('rating'), Value(0))
)['max_rating']

To maybe improve on @afahim answer with regards to @Raydel Miranda comment, if you want a random comment. If you want all, then use just the filter

from django.db.models import Max

# Find the maximum value of the rating and then get the record with that rating. 
# Notice the double underscores in rating__max
max_rating = App.objects.aggregate(Max('rating'))['rating__max']
return App.objects.filter(rating=max_rating).first()

maybe it will help someone's trouble

def get_queryset(self):
    sorgu = Sunum.objects.values('id', 'firma', 'projeadi', 'sunumdurum__durum', 'sunumdurum__aciklama'
                           ).annotate(max_rank=Max('sunumdurum__kayittarihi'))
    szlk={}
    for sor in sorgu :
        ana = sor['id'], sor['firma'], sor['projeadi']
        dana = sor['sunumdurum__durum'], sor['sunumdurum__aciklama'], sor['max_rank']
        szlk.setdefault(ana, dana)
    return szlk
Related