18

しばらく前に使用した django ページネーションのコード例がいくつかありました。私は間違っているかもしれませんが、コードを見てみると、大量のメモリを浪費しているように見えます。私はより良い解決策を探していました。コードは次のとおりです。

# in views.py
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger

... 
...    

def someView():
    models = Model.objects.order_by('-timestamp')
    paginator = Paginator(models, 7)
    pageNumber = request.GET.get('page')

    try: 
        paginatedPage = paginator.page(pageNumber)
    except PageNotAnInteger: 
        pageNumber = 1
    except EmptyPage: 
        pageNumber = paginator.num_pages
    models = paginator.page(pageNumber)

    return render_to_resp ( ..... models ....)

このコードの詳細はわかりませんが、コードの最初の行でデータベースからすべてのモデルを取得し、プッシュします。次に、それは Paginator に渡され、ユーザーが html GET から表示しているページに基づいて分割されます。ページネーターは何とかこれを受け入れられるようにしていますか、それともこれは完全にメモリ効率が悪いのでしょうか? 効率が悪い場合、どのように改善できますか?

また、関連トピック。誰かがそうする場合:

   Model.objects.all()[:40]

このコードは、すべてのモデルがメモリにプッシュされ、そのうちの 40 個をつなぎ合わせるという意味ですか? これは悪いことです。それとも、クエリを実行して 40 個のオブジェクトのみをメモリ期間にプッシュするということですか?

ご協力ありがとうございました!

4

3 に答える 3

27

mymodel.objects.all()リストではなく、クエリセットを生成します。クエリセットは遅延型です。実際に使用するまで、リクエストは発行されず、何も行われません。また、クエリ セットをスライスしても、サブセットを取得するためだけにすべてをメモリにロードするのではなく、データベースにアクセスする前に SQL クエリに制限とオフセットを追加します。

于 2013-04-23T07:11:25.760 に答える
1

ページネーターを使用する場合、メモリ効率が悪いということはありません。クエリセットは遅延評価されます。あなたの呼び出しPaginator(models, 7)modelsは、この時点まで評価されていないクエリセットです。そのため、今までデータベースはヒットしていません。また、この時点では、モデルのすべてのインスタンスを含むリストはメモリにありません。

ページ、つまり を取得したい場合paginatedPage = paginator.page(pageNumber)、このクエリセットでスライスが行われます。この時点でのみデータベースがヒットし、データベースはモデルのインスタンスを含むクエリセットを返します。そして、スライスはページ上にあるはずのオブジェクトのみを返します。そのため、スライスされたオブジェクトのみがリストに入り、メモリに存在します。あるページで 10 個のオブジェクトを表示したいとします。これらの 10 個のオブジェクトのみがメモリに残ります。

誰かがそうするとき。

Model.objects.all()[:40]

リストをスライスすると、新しいリストが作成されます。あなたの場合、リストは40要素のみで作成され、メモリのどこかに保存されます。Model他のリストは存在しないため、メモリ内のすべてのインスタンスを含むリストはありません。

于 2013-04-23T05:58:27.373 に答える