2009-05-10 11 views
48

Ich habe eine Liste von Objekten, wie kann ich eine Abfrage ausführen, die maximale Wert eines Feldes zu geben:Wie man SELECT MAX in Django macht?

Ich verwende diesen Code:

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

Rating ist eine ganze Zahl

Antwort

97

See this. Ihr Code würde in etwa wie folgt sein:

from django.db.models import Max 
# Generates a "SELECT MAX..." statement 
Argument.objects.all().aggregate(Max('rating')) 

Wenn Sie bereits die Liste aus der Datenbank bekommen haben, dann würden Sie so etwas tun:

from django.db.models import Max 
args = Argument.objects.all() 
# Calculates the maximum out of the already-retrieved objects 
args.aggregate(Max('rating')) 

Das so ungetestet ist I Vielleicht hast du irgendwo einen Fehler gemacht, aber da gehst du hin.

+0

Tippfehler: "Import Avg" -> "Import Max"? – Tom

+0

ja ich machte diese Änderung in meinem Code – Johnd

+4

Ich brauche das tatsächliche Argument-Objekt, das Max hat, damit ich das Detailfeld drucken kann. Der Aufruf args.aggregate (Max ('rating')) liefert nur die höchste Bewertung. Ich suche nach dem arg mit der höchsten Bewertung. – Johnd

37

Ich habe getestet dies für mein Projekt, findet es der max/min in O (n) Zeit:

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) 

Dies wird garantiert, dass Ihnen eine der maximalen Elemente effizient zu bekommen, anstatt die Sortier ganzer Tisch und oben (um O (nlogn)).

+4

Big-O in der Praxis manchmal nicht aus, vor allem für kleinere n, wo Koeffizienten und die Umsetzung von Bedeutung. Ihr Code ist in Python/Django, die zu Bytecode kompiliert wird und möglicherweise nicht optimiert werden kann. Die Datenbank wird wahrscheinlich in einer Sprache geschrieben, die optimiert und zu Maschinenbefehlen kompiliert ist. Außerdem hat die Datenbank keinen wirklichen Grund zu sortieren, wenn die Funktion nur nach einem maximalen Wert sucht. Ich möchte Timing-Daten sehen, bevor ich mich mit Hand-Build-Code über eine integrierte Datenbankfunktion wohl fühlen kann. – benevolentprof

46

Django hat auch die 'latest(field_name = None)' Funktion, die den neuesten (max. Wert) Eintrag findet. Es funktioniert nicht nur mit Datumsfeldern, sondern auch mit Strings und ganzen Zahlen.

können Sie den Feldnamen geben, wenn diese Funktion aufgerufen wird:

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

Oder Sie können bereits diesen Feldnamen in Ihren Modellen Meta-Daten geben:

from django.db import models 

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

Jetzt können Sie ‚neueste nennen () 'ohne Parameter:

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

Dies ist eine großartige Möglichkeit, 'latest()' zu verwenden. Wenn Sie den Datensatz mit dem Mindestwert benötigen, können Sie 'frühest()' verwenden. – SaeX

+1

'neustes()' und 'frühestes()' funktioniert auch mit Nicht-Datum-Feld, aber es ist ein Nebeneffekt der Implementierung. Sie sollten ' .order_by (''). First()' oder ' .order_by ('') verwenden.last() ', um sicherzustellen, dass Ihr Code auch dann noch funktioniert, wenn Django-Entwickler' neuste() 'und' früheste() 'Implementierung ändern, um nur mit Datumsfeldern zu arbeiten. – mrnfrancesco