web-dev-qa-db-fra.com

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

note est un entier

72
Johnd

Voir ceci . Votre code ressemblerait à ceci:

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 ensembles de requêtes 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 de modèle qui contient cette valeur maximale, le code que vous avez publié est probablement le meilleur moyen de le faire:

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

Notez que cela générera une erreur si l'ensemble de requêtes est vide, c'est-à-dire si aucun argument ne correspond à la requête (car la partie [0] Lèvera un IndexError). Si vous voulez éviter ce comportement et retourner simplement à la place None dans ce cas, utilisez .first() :

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

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

Vous pouvez donner le nom du champ lors de l'appel de 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
65
Lutz Schönemann

J'ai testé cela pour mon projet, il trouve le max/min dans O(n) time:

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.all().aggregate(Max('rating'))['rating__max']
return App.objects.get(rating = max_rating)

Cela vous garantit d'obtenir l'un des éléments maximaux efficacement, plutôt que de trier la table entière et d'obtenir le haut (autour de O (nlogn)).

41
afahim