2016-05-08 9 views
2

ユーザーが写真をアップロードしてコメントを残すDjangoアプリがあります。これらのオブジェクトを反映するデータモデルは、それぞれPhotoPhotoCommentです。Djangoクエリーセット関連の比較を最適化する

PhotoThreadSubscriptionという3番目のデータモデルがあります。ユーザーが写真の下でコメントするたびに、ユーザーはPhotoThreadSubscriptionにオブジェクトを作成することによってその特定のスレッドにサブスクライブされます。このようにして、後で他のユーザーが同じスレッドに残したコメントを知ることができます。

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

写真の下のユーザーがコメントするたびに、私は、その特定の写真のためのユーザのPhotoThreadSubscriptionオブジェクトのviewed_at属性を更新します。 他のユーザーの投稿は、その特定のスレッドの投稿時間がviewed_atより大きいので、新しいです。

私はコメントのクエリーセットを持っているとします。これらのコメントは、決して繰り返されないユニークな写真に属しています。私はこのクエリーセットを横断して、最新の見えないコメントを探しています。

現在、私は非常に重いDB方法でこれをしようとしている:

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 

これは明らかにそれを行うには良い方法ではありません。 1つは、forループでDB呼び出しをしたくないということです。 1回のコールで上記をどのように管理できますか?具体的には、1回の呼び出しで適切なPhotoThreadSubscriptionクエリーセットを取得するにはどうすればいいですか?次に、それを使ってmax_unseen_commentを計算するにはどうすればよいですか?私は今非常に混乱しています。


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) 

質問がかすんで見えた場合明確化のためにお問い合わせください。私は、これは単一のクエリでそれを行うだろうと思い

答えて

2

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

キーここでは、比較は、各コメントの個々の日付で行うことができるようにF expressionsを使用してではなく、中にハードコード単一の日付を使用していますクエリ。目に見えないコメントのみを含めるようにクエリセットをフィルタリングした後、コメントの日付をorder_byとし、最初のコメントを取ります。

関連する問題