2009-08-22 10 views
2

ich eine grundlegende FK Benutzer haben, rufen sie BesitzerDjango-queryset bekommen ein Objekt pro Feld = foo

class Baz(models.Model): 

    owner = models.ForeignKeyField(User) 


    .... 
    .... 

nun mit einem queryset von Baz, gibt es so etwas kann ich Kette, die mir geben nur ein Baz pro Besitzer?

+0

Wenn Sie also ein QuerySet von Baz angeben, möchten Sie es so filtern, dass keine zwei vom QuerySet zurückgegebenen Objekte dasselbe Benutzerobjekt wie der Eigentümer haben. Ist es das was du willst? – ayaz

+0

Klingt, als ob Sie die Idee hätten –

Antwort

1

Dies ist wahrscheinlich nicht die beste Lösung (möchte, um es aus der Erinnerung und in querysets), aber:

>>> d={} 
>>> [d.setdefault(str(a.owner),a) for a in qs ] 
>>> d.values() 

tut Rückkehr eine Liste von Objekten, die neuesten für jeden Besitzer. Ich habe echte Bedenken bezüglich der Skalierbarkeit dieser Lösung.

+0

Ich würde vorschlagen, diese Lösung zu verwenden und sie später zu optimieren, wenn es ein Problem wird. Vielleicht notieren Sie sich, um später darauf zurückzukommen und es zu beheben. –

+0

Danke, ich benutze das auch, obwohl ich es hasse. Wenn Sie diesen Code verbessern, können Sie Ihre Verbesserung posten? – slypete

0

EDIT: Dies hat eine höhere Chance Arbeits:

CheckIn.objects.extra(where=['checkins_checkin.id = (SELECT MAX(checkins_checkin.id) FROM checkins_checkin temp, auth_user WHERE auth_user.id = temp.id AND temp.user_id = checkins_checkin.user_id)',]).count() 
+0

CheckIn.objects.extra (where = ['checkins_checkin.id = (SELECT checkins_checkin.id FROM checkins_checkin temp, auth_user WHERE auth_user.id = temp.id ORDER BY id DESC LIMIT 1)',]) .count() Aus [4]: ​​18 In [5]: CheckIn.objects.all(). count() Aus [5]: 18 –

+0

es gibt nur 2 Besitzer in diesem Test-Datensatz, aber ich bekomme Zurück alle 18 Objekte mit dieser Abfrage. –

+0

Sie haben Recht, ich habe vergessen, die Benutzerkriterien in der Where-Klausel hinzuzufügen. Ich habe meine Antwort entsprechend aktualisiert. – shanyu

2

Die Funktion, die Sie wirklich für Ihre Suche ist GROUP BY. Django unterstützt jedoch normalerweise nicht die Erstellung von Abfragegruppen, die keine Modellinstanzen direkt ausgeben. In dieser Situation haben Sie zwei approachs:

Baz.objects.values('owner').distinct() 

Dies werden Sie jeden einzelnen Eigentümer Netz, aber nicht die Baz selbst widersprechen.

Baz.objects.filter(pk__in=Baz.objects.values('owner').distinct()) 

Die oben wird eine Unterabfrage (zumindest in MySQL) durchführen und sollten die beabsichtigten Ergebnisse geben, aber es ist nicht der effizienteste Weg, um es abzurufen.

Schließlich, da Aggregate hinzugefügt wurden, können Sie möglicherweise eine benutzerdefinierte Aggregatklasse schreiben, die als eine Art "Distinct" und einfach "GROUP BY" funktionieren würde.

+0

Ihre zweite Abfrage ergibt [] .... –

+0

Ah, die Unterabfrage ist nicht ganz richtig, verwenden Sie die folgende Gruppe, whoi s unten gezeigt. –

3

Ich glaube, die Frage ist, wie das Äquivalent von dieser auszuführen:

SELECT * FROM myapp_baz GROUP BY owner_id; 

Welche eine Zeile für jede einzelne owner_id zurück.

Es sieht wie folgt aus funktioniert der Trick:

qs = Baz.objects.all() 
qs.query.group_by = ['owner_id'] 

# Seems to do the trick 
print [item for item in qs] 
+0

scheint so nah, ich werde das weiter untersuchen. Spalte "app_baz.X" muss in der GROUP BY-Klausel erscheinen oder in einer Aggregatfunktion verwendet werden –

+0

Können Sie ein Code-Snippet bereitstellen? In meinem Beispiel ist "owner_id" eine Spalte in der Datenbank (und wenn Ihr Baz-Objekt "owner = ForeignKey (SomeObject)" hat, sollten Sie auch eine owner_id-Spalte haben). – tvon

+0

owner_id ist eine Spalte, ich ProgrammingError: Spalte „checkins_checkin.id“ in der GROUP BY-Klausel erscheinen müssen oder in einer Aggregatfunktion checkins_checkin.id der Primärschlüssel verwendet werden .. aber dann, wenn ich hinzufügen, dass Zur group_by-Liste geht es dann weiter mit dem gleichen Fehler für das nex-Feld. –

Verwandte Themen