2016-05-08 24 views
2

Ich habe eine Django App, wo Benutzer Fotos hochladen und Kommentare hinterlassen. Die Datenmodelle, die diese Objekte widerspiegeln, sind Photo bzw. PhotoComment.Django Queryset Vergleiche optimieren

Es gibt ein drittes Datenmodell mit der Bezeichnung PhotoThreadSubscription. Immer wenn ein Benutzer unter einem Foto einen Kommentar abgibt, wird dieser bestimmte Thread abonniert, indem ein Objekt in PhotoThreadSubscription erstellt wird. Auf diese Weise kann er/sie über Kommentare informiert werden, die später von anderen Benutzern in demselben Thread hinterlassen wurden.

class PhotoThreadSubscription(models.Model): 
    viewer = models.ForeignKey(User) 
    viewed_at = models.DateTimeField(db_index=True) 
    which_photo = models.ForeignKey(Photo) 

Jedes Mal, wenn ein Benutzer Kommentare unter einem Foto, aktualisiere ich die viewed_at Attribut des PhotoThreadSubscription Objekt des Benutzers für das jeweilige Foto. Alle Kommentare von andere Benutzer, die eine Übermittlungszeit von mehr als viewed_at für diesen bestimmten Thread haben, sind daher neue.

Angenommen, ich habe eine Reihe von Kommentaren, die alle zu eindeutigen Fotos gehören, die sich nie wiederholen. Ich möchte dieses Abfrage-Set durchlaufen und den neuesten unsichtbaren Kommentar finden.

Derzeit bin ich versucht, dies in einer sehr schweren DB Weg:

latest_unseen_comment = PhotoComment(id=1) #i.e. a very old comment 
for comment in comments: 
    if comment.submitted_on > PhotoThreadSubscription.objects.get(viewer=user, which_photo_id=comment.which_photo_id).viewed_at and comment.submitted_on > latest_unseen_comment.submitted_on: 
     latest_unseen_comment = comment 

Das ist natürlich kein guter Weg, es zu tun. Zum einen möchte ich keine DB-Aufrufe in einer for-Schleife machen. Wie verwalte ich das oben genannte in einem Anruf? Genauer gesagt, wie bekomme ich den relevanten PhotoThreadSubscription Queryset in einem Anruf, und wie kann ich das dann verwenden, um den max_unseen_comment zu berechnen? Ich bin gerade sehr verwirrt.


class Photo(models.Model): 
    owner = models.ForeignKey(User) 
    image_file = models.ImageField(upload_to=upload_photo_to_location, storage=OverwriteStorage()) 
    upload_time = models.DateTimeField(auto_now_add=True, db_index=True) 
    latest_comment = models.ForeignKey(blank=True, null=True, on_delete=models.CASCADE) 


class PhotoComment(models.Model): 
    which_photo = models.ForeignKey(Photo) 
    text = models.TextField(validators=[MaxLengthValidator(250)]) 
    submitted_by = models.ForeignKey(User) 
    submitted_on = models.DateTimeField(auto_now_add=True) 

Bitte um Klärung fragen, ob die Frage trübe schien.

Antwort

2

ich denke, das es in einer einzigen Abfrage tun:

latest_unseen_comment = (
    comments.filter(which_photo__photothreadsubscription__viewer=user, 
        which_photo__photothreadsubscription__viewed_at__lt=F("submitted_on")) 
      .order_by("-submitted_on") 
      .first() 
) 

Der Schlüssel hier ist F expressions so dass der Vergleich mit mit jedem Kommentar individuellem Datum erfolgen, anstatt ein einzelnes Datum in der fest einprogrammiert mit Abfrage. Nach dem Filtern des Abfrage-Sets, um nur die Kommentare zu erfassen, die ungesehen sind, nehmen wir dann das Datum order_by des Kommentars und nehmen das erste.