2011-07-11 24 views
2

私はDjangoでいくつかの並べ替えオプションを使用してページネーション構造を実装しようとしていますが、どうすれば適切に行うことができないのでしょうか。ソートによるDjangoページ分割のオーバーヘッド

views.py

def search(request): 
    eList = Employer.objects.filter(eminence__lt=4).order_by('-eminence') 

    paginator = Paginator(eList, 3) # Show 3 contacts per page 

    page = request.GET.get('page') 
    try: 
     employerList = paginator.page(page) 
    except PageNotAnInteger: 
     employerList = paginator.page(1) 
    except EmptyPage: 
     employerList = paginator.page(paginator.num_pages) 

return render_response(request, 'employer/search.html', {'employerList':employerList}) 

search.htmlの

<div class="pagination"> 
    <span class="step-links"> 
     {% if employerList.has_previous %} 
      <a href="?page={{ employerList.previous_page_number }}">previous</a> 
     {% endif %} 

     <span class="current"> Page {{ employerList.number }} of {{ employerList.paginator.num_pages }}.</span> 
     {% if employerList.has_next %} 
      <a href="?page={{ employerList.next_page_number }}">next</a> 
     {% endif %} 
    </span> 
</div> 

この例では、しかし、あなたは私がすべてのEmployerオブジェクトを取得する必要があり、すべてのナビゲーションのために、見ることができるように素晴らしい作品。その後、Paginatorは、ページ番号に応じてクエリ内のオブジェクトを処理します。しかし、私はページネーションがクエリ中に実行され、ページ番号に依存したいXオブジェクトだけを取得する必要があると思います。私はそのような方法でコードを変更することができますが、そのようなオーバーヘッドがあるにもかかわらず、人々がなぜPaginatorを使用するのか理解できません。私は詳細を見落とすかもしれません...

私の2番目の質問はどのように私のリストを並べ替えることができますか? urlを変更し、ソート方法とページ番号を渡す必要があります。それらに応じて、ソート方法によってクイズが得られ、それをPaginatorにしますか?

これは私にとっては妥当で素晴らしいと思われますが、私はちょうどdjangoで行うより良いアプローチがあるのだろうかと思います。

おかげ

答えて

6

Djangoはこれらのクエリは非常に効率的にデータを、遅延ロードについて非常にスマートです。さんがあなたの要求に何が起こるか見てみましょう...あなたの並べ替え問題については

eList = Employer.objects.filter(eminence__lt=4).order_by('-eminence') 
## No database query. 

paginator = Paginator(eList, 3) 
## No database query. 

employerList = paginator.page(2) 
## SELECT COUNT(*) FROM `yourproject_employer` 
## WHERE `yourproject_employer`.`eminence` < 4 

# Force iteration. Same as looping over results: 
foo = list(employerList.object_list) 
## SELECT * FROM `yourproject_employer` 
## WHERE `yourproject_employer`.`eminence` < 4 
## ORDER BY `yourproject_employer`.`eminence` DESC 
## LIMIT 3 OFFSET 3 

、私はあなたが示唆したように、単にGET引数を変更すると言うでしょう。ただ非常にデータベースにこれを渡す注意してください。私は、たとえば、可能な並べ替えのリストを作成し、それに対して検証します。つまり、データベースの内部動作を公開する必要はありません。

VALID_SORTS = { 
    "pk": "pk", 
    "pkd": "-pk", 
    "em": "eminence", 
    "emd": "-eminence", 
} 
DEFAULT_SORT = 'pk' 
def search(request): 
    sort_key = request.GET.get('sort', DEFAULT_SORT) # Replace pk with your default. 
    sort = VALID_SORTS.get(sort_key, DEFAULT_SORT) 

    eList = Employer.objects.filter(eminence__lt=4).order_by(sort) 
+0

私はそれを知っていましたdjangoの開発者はよりスマートなtahnです:)私は "それ以外の場合"のコントロールを適用していた方法でセキュリティのおかげで感謝しますが、より洗練されたソリューションのようです – brsbilgic

+0

私は実際に私のサイトでこれを90%私は助けてうれしいです。 '= - ]' –

0

実際には、ページマネージャはQuerySetのスライシングに依存しています。スライシングは、特定のデータベースに依存します - もしdjango dbアダプタがそれをサポートしていれば(例えばスライス制限をSQLクエリに移します - mysqlの場合はLIMIT x OFFSET y、他のdbの場合は何かに)これがサポートされている場合、クエリは指定されたページの行のみを取得します。
私は、OFFSET句の性能上の問題のため、MySQLではこの機能が現在無効になっていると考えています(私はDjango 1.3を検討していました)。

関連する問題