2013-08-14 2 views
6

Ich möchte mehrere Querysets in Django anhängen oder verketten, wobei die Reihenfolge jedes einzelnen (nicht das Ergebnis) erhalten bleibt. Ich verwende eine Bibliothek eines Drittanbieters, um das Ergebnis zu paginieren, und akzeptiert nur Listen oder Abfragegruppen. Ich habe diese Optionen ausprobiert:So verketten Sie Django-Querysets, die individuelle Reihenfolge erhalten

Queryset Join: Sortierung in einzelnen Abfragesätzen nicht beibehalten, so kann ich dies nicht verwenden.

result = queryset_1 | queryset_2 

Mit itertools: list() an der Kette Objekt aufrufen wertet tatsächlich die querysets und dies viel Aufwand verursachen könnte. Nicht wahr?

result = list(itertools.chain(queryset_1, queryset_2)) 

Wie soll ich gehen?

Antwort

4

Wenn die querysets der verschiedenen Modelle sind, müssen Sie sie auf Listen bewerten und dann können Sie einfach anhängen:

result = list(queryset_1) + list(queryset_2) 

Wenn sie das gleiche Modell sind, sollten Sie die Abfragen kombinieren mit der Q object und ' order_by ("queryset_1 field", "queryset_2 field") ".

Die richtige Antwort hängt weitgehend davon ab, warum Sie diese kombinieren und wie Sie die Ergebnisse verwenden möchten.

+0

Ich bin in mehreren Abfragen gespaltet eine komplexe Suchanfrage auf dem gleichen Modell zu tun. Jeder ruft Datensätze ab, die einer bestimmten Bedingung entsprechen und jeder auf eine bestimmte Weise geordnet ist. Das Ergebnis muss die Ergebnisse der einzelnen Abfragegruppen enthalten und die Reihenfolge der einzelnen Abfragegruppen beibehalten. Daher kann ich hier keine 'Q' Objekte verwenden, da ich in derselben Abfrage nicht mehrere' order_by() 'machen könnte. Ich möchte vermeiden, 'list()' auf jedem Abfrage-Set aufzurufen, um den Zugriff auf die Datenbank zu vermeiden und zu viele Objekte im Speicher zu erhalten. – Caumons

+0

Denkst du, dass es möglich ist, eine reine SQL-Abfrage zu erstellen, die einen einzelnen Satz von Zeilen zurückgibt, die genau nach Ihren Wünschen geordnet und gefiltert werden? Wenn nicht, dann kann ein einzelner QuerySet dies auch nicht tun.Wenn Sie beispielsweise zwei Ergebnismengen auf inkompatible Weise bestellen. Wenn Sie diese Inkompatibilität mit einem komplexen Join aus zwei eindeutig geordneten Resultsets umgehen, ist das etwas, was django ORM nicht kann. – Demiurge

+0

Ich möchte nicht so sehr in pures SQL einsteigen, wie ich bei Djangos ORM bleiben kann. Ich habe nur gefragt, ob es eine bessere Alternative für das, was ich gerade tue (derzeit im zweiten Beispiel), mit einer begrenzten Abfrage gibt, um zu vermeiden, dass Tausende von Objekten im Speicher sind. – Caumons

0

Wenn Sie zwei Abfragesätze in einem dritten Abfragesatz zusammenführen müssen, ist hier ein Beispiel mit _result_cache.

Modell

class ImportMinAttend(models.Model): 
    country=models.CharField(max_length=2, blank=False, null=False) 
    status=models.CharField(max_length=5, blank=True, null=True, default=None) 

Von diesem Modell möchte ich von allen Zeilen einer Liste angezeigt werden, so dass:

  1. (Abfrage 1) leer Status zuerst nach Ländern geordnet gehen,
  2. (Abfrage 2) nicht leer Status gehen in Sekunde, sortiert nach Ländern

möchte ich Abfrage 1 und Abfrage 2.

#get all the objects 
    queryset=ImportMinAttend.objects.all() 

    #get the first queryset 
    queryset_1=queryset.filter(status=None).order_by("country") 
    #len or anything that hits the database 
    len(queryset_1) 

    #get the second queryset 
    queryset_2=queryset.exclude(status=None).order_by("country") 

    #append the second queryset to the first one AND PRESERVE ORDER 
    for query in queryset_2: 
     queryset_1._result_cache.append(query) 

    #final result 
    queryset=queryset_1 

Es ist vielleicht nicht sehr effizient sein fusionieren, aber es funktioniert :).

+0

Dies scheint sehr viel effizienter zu sein als das Aufrufen von list() in beiden Abfragegruppen. Wenn Sie über das kleinste iterieren, scheint dies besser. Was ich nicht mag, ist das private Attribut _result_cache zu modifizieren ... Sind Sie sicher, dass das sicher ist? – Caumons

+0

Dieser Ansatz wird immer noch alle Abfragegruppen auswerten, was mit dem Erstellen einer Liste von ihnen übereinstimmt, was der Autor der Frage nicht möchte. –