2009-06-29 11 views
4

Soll entry_set mit select_related gespeichert werden? Meine DB erhält immer noch Anrufe, auch wenn ich select_related verwende. Die entsprechenden Abschnittedjango: select_related with entry_set

class Alias(models.Model): 
    achievements = models.ManyToManyField('Achievement', through='Achiever') 

    def points(self) : 
     points = 0 
     for a in self.achiever_set.all() : 
      points += a.achievement.points * a.count 
     return points 

class Achievement(models.Model): 
    name = models.CharField(max_length=100) 
    points = models.IntegerField(default=1) 

class Achiever(models.Model): 
    achievement = models.ForeignKey(Achievement) 
    alias = models.ForeignKey(Alias) 
    count = models.IntegerField(default=1) 

aliases = Alias.objects.all().select_related() 
for alias in aliases : 
    print "points : %s" % alias.points() 
    for a in alias.achiever_set.all()[:5] : 
     print "%s x %d" % (a.achievement.name, a.count) 

Und ich sehe eine große Join-Abfrage am Anfang und dann individuelle Anrufe für jeden Erfolg. Sowohl für die Punkte als auch für die Namenssuche.

Ist das ein Fehler, oder mache ich etwas falsch?

Antwort

4

Select_related() funktioniert nicht mit manytomanyfields. Im Moment ist dies etwas, das nicht geplant ist, aber ein zukünftiges Feature sein könnte. Siehe http://code.djangoproject.com/ticket/6432

In diesem Fall, wenn Sie eine einzige Abfrage erstellen möchten, haben Sie zwei Optionen 1) Machen Sie Ihre eigenen SQL, wird wahrscheinlich nicht schön oder schnell sein. 2) Sie können das Modell auch mit dem Fremdschlüssel abfragen. Sie könnten select_related in diesem Fall verwenden. Sie können immer noch nicht auf den Modellnamen zugreifen, aber mit einigen Formatierungen können Sie die benötigten Daten in einer einzigen Abfrage überprüfen. Keine der Optionen ist ideal, aber Sie könnten es auch mit einer entsprechenden Geschwindigkeit arbeiten lassen.

+0

Bummer. Wie würden Sie mir empfehlen, diese Abfrage durchzuführen? SQL von Hand? –

+5

Für jeden Leser, ein 'select_related()' Äquivalent für M2M und umgekehrt FK ist 'prefetch_related()' und wurde in 1.4 hinzugefügt. – Bryan

+0

googletorp und @Bryan, danke SO VIEL. – Jamey

0

In Django 1.3 Sie können Queryset.values ​​() und wie etwas tun:

Alias.objects[.filter().exclude() etc.].values('achievements__name', 'achievement__points') 

Nur drwaback ist, dass Sie QuerySetList statt QuerySet bekommen. Dies kann aber nur, indem alle notwendigen Felder in Werte() überwunden werden - Sie haben Ihre Wahrnehmung zu ändern;)

Diese Sie wenige dosen von Abfragen speichern ...

Details finden Sie hier in django finden docs: http://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.values