122 votes

Comment faire SELECT MAX dans Django ?

J'ai une liste d'objets, comment puis-je exécuter une requête pour donner la valeur maximale d'un champ :

J'utilise ce code :

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

l'indice est un nombre entier

214voto

Sasha Chedygov Points 36783

Voir este . Votre code serait quelque chose comme le suivant :

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

Vous pouvez également l'utiliser sur des querysets existants :

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

Si vous avez besoin de l'instance du modèle qui contient cette valeur maximale, alors le code que vous avez posté est probablement la meilleure façon de le faire :

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

Notez que cette opération se soldera par une erreur si l'ensemble de requêtes est vide, c'est-à-dire si aucun argument ne correspond à la requête (parce que l'attribut [0] soulèvera un IndexError ). Si vous souhaitez éviter ce comportement et renvoyer simplement le message None dans ce cas, utilisez .first() :

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

85voto

Django dispose également de la fonction ' latest(field_name = None) La fonction ' qui trouve la dernière entrée (valeur maximale). Elle fonctionne non seulement avec les champs de date mais aussi avec les chaînes de caractères et les entiers.

Vous pouvez donner le nom du champ lorsque vous appelez cette fonction :

max_rated_entry = YourModel.objects.latest('rating')
return max_rated_entry.details

Ou vous pouvez déjà donner ce nom de champ dans les métadonnées de vos modèles :

from django.db import models

class YourModel(models.Model):
    #your class definition
    class Meta:
        get_latest_by = 'rating'

Vous pouvez maintenant appeler 'latest()' sans aucun paramètre :

max_rated_entry = YourModel.objects.latest()
return max_rated_entry.details

52voto

afahim Points 123

Je l'ai testé pour mon projet, il trouve le max/min en O(n) temps :

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.get(rating=max_rating)

Cela permet d'obtenir efficacement l'un des éléments maximums, plutôt que de trier l'ensemble du tableau et d'obtenir le maximum (environ O(n*logn)).

5voto

roskakori Points 598

Si vous souhaitez également obtenir une valeur autre que None dans le cas où le tableau est vide (par exemple 0), combiner Max con Coalescence :

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']

5voto

Dipta Dhar Points 61

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'))

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X