2016-05-12 4 views
1

私はdjangoフォーラムで、私は嫌がらせをしているユーザーを4日間、維持しています。フォーラムの「ホームページ」では、全員のコメントを表示しますが、地獄で禁止されている人のコメントは除外しています。それはこのように書きます:スライスを撮影した後にDjangoクエリーセットをフィルタリングする

def get_queryset(self): 
     if self.request.user_banned: #if user is hell-banned 
      return Link.objects.order_by('-id')[:120] 
     else: #if user is not hell-banned 
      global condemned 
      queryset = Link.objects.order_by('-id').exclude(submitter_id__in=condemned)[:120] 
      return queryset 

上記はListViewget_queryset方法です。地獄の禁止されたユーザーが、自分のコメントがサイトから除外されていると言うことができないことに注目してください(地獄禁止のポイント)。 condemnedは、地獄で禁止されたユーザーの主キーを含むリストです。

今、私は上記をでスライスし、後で禁止された人々を除外してに最適化したいと思います。

Cannot filter a query once a slice has been taken.

私はどのような選択肢があります:

def get_queryset(self): 
    if self.request.user_banned: #if user is hell-banned 
     return Link.objects.order_by('-id')[:120] 
    else: #if user is not hell-banned 
     global condemned 
     queryset = Link.objects.order_by('-id')[:120] 
     queryset = queryset.exclude(submitter_id__in=condemned) 
     return queryset 

これはunfotunately私にエラーを与える:私は経由していることをやろうとしていますか?パフォーマンスが重要なので、私が見つけることができる最も効率的なソリューションが必要です。私はDjangoにいます< 1.8。前もって感謝します。

+1

特にDjangoのバージョンは? Django <1.8は不必要に曖昧です。 – wim

+0

@wim:Django 1.7。 –

+0

クエリの取得時間はどのくらいですか?なぜ、「最初にスライスし、後に禁止された人々を除外する」がより速くなると思いますか? 'submitter_id'は外部キーですか? 「非難」リストはどれくらいの大きさですか? – Alasdair

答えて

0

最初に、Djangoはスライスの後にフィルタリングさせません。基本となるSQLでは、結果がlimitで簡単にはできないため、whereでフィルタリングすることができます。

フィルタリングを行うと、スライスはおそらく問題ありません。 querysets are lazyになるので、Djangoはdbから120個のオブジェクトしか取得しません。

エクスクルードが実際にあなたを減速させるかどうかを調べるには、ベンチマークを行う必要があります。 excludeとsliceを含むクエリがスライスだけのクエリよりも著しく遅いかどうかをテストできます。

あなたは除外するが遅いことが判明した場合、あなたは

comments = [c for c in comments if c.submitter_id not in condemned]. 

にはPython

にあなたがより少ない120件のコメントこのように終わる可能性があり注意をフィルタリングすることができます。

もう1つの方法は、フラグをSubmitterモデルに追加してから、クエリを.exclude(submitter__condemned=True)に変更することです。これは現在の.exclude(submitter_id__in=condemned)より速いかもしれません。

また、データベースにsubmitter_idフィールドのインデックスがあることを確認する必要があります。それは外来キーなので、おそらくそうです。

関連する問題