2011-03-01 29 views
9

は、djangoの組み込みページネーションを使用してrawqueretetを改ページする方法ですか? 私はそれをリストにキャストすると、私の顔にエラーがスローされます... TypeError:期待される文字列またはUnicodeオブジェクト、NoneTypeが見つかりました。これを回避する方法はありますか?djangoのページ番号とRawQuerySet

答えて

14

私は、次を使用してそれを達成するために管理:

paginator = Paginator(files, 12) 
paginator._count = len(list(files)) 

django.core.paginator.pyのコード:_countが設定されているかどうかを

  • そして、そうでない場合の試行のための

    • チェック存在しない.count()を実行するには
    • もしそうでなければ、lenをプレーします。

    は動作しませんが、リストに実際のページネータオブジェクトを変換すると、Djangoの中で私を見つける作品raw_querysetにlenの1.3

  • +7

    明らかでlen(リスト(ファイル))のために非常に大きなメモリの生のクエリセットの非効率的です。実行されたクエリが分かっている場合、代わりにCOUNT(*)を使用して別のクエリを実行し、各クエリ間で結果の数が変化しない限りpaginator._countに代入することができます。 また、異なるDBMSには、クエリ結果が絶えず変化している場合に、クエリのすべての行に合計行数を埋め込む方法があります。 – Chris

    +0

    残念ながら、[RawQuerySet .__ getitem__()](https://code.djangoproject.com/browser/django/trunk/django/db/models/query.py?rev=17381#L1517)コールリスト(自己)とにかく - 'paginator.get_page()'を呼び出すとすぐに完全にメモリにロードされます。これを避けるには、RawQuerySetをサブクラス化して、生のSQLにLIMIT/OFFSETがあることを確認する必要があります。通常のクエリーセットの結果キャッシュを失うことになるので、qs [0] DBに2回ヒットします。 – AdamKG

    +0

    はい、2回ヒットします。私はちょうどそれ自身のためにそれを発見した。だから最善のあなたは、その生のクエリーセットのために非常に効率的なSQLを書くと、生のクエリーセットをlen(list())に渡すのではなく、ページネーターに渡してクエリーセットをルーペで評価します。 l = [querysetの項目の項目]のようにして、そのlをpaginatorとlen(l)の両方に渡します。これにより、データベース呼び出しは1つだけになります。 –

    4
    あなたは属性があなたのRawQuerySetオブジェクトに手動でカウントを設定することができ

    items = Item.objects.raw("select * from appitem_item") 
    
    def items_count(): 
        cursor = connection.cursor() 
        cursor.execute("select count(*) from appitem_item") 
        row = cursor.fetchone() 
        return row[0] 
    
    items.count = items_count 
    

    @Rockallite

    >>> class A(): 
    ... def b(self): 
    ...  print 'from b' 
    ... 
    >>> 
    >>> (A()).b() 
    from b 
    >>> def c(): 
    ... print 'from c' 
    ... 
    >>> a = A() 
    >>> a.b = c 
    >>> a.b() 
    from c 
    
    +0

    django.core.paginator.Paginatorは 'count()'メソッドを探します。したがって、 'count'プロパティの設定は機能しません。 – Rockallite

    +0

    なぜ、あなたはそれを試しましたか?もちろん、それはハックですが、私はそれを使用しました。私は、Pythonでは、あるメソッドを別のものに置き換えることができるということです。 –

    +0

    Rockallite、このハックの仕組みを説明するためにコードを追加しました –

    -2
    qs.filter(**pfilter).distinct().extra(select={'test': 'COALESCE(`psearch_program`.`eu_price`, 999999999)'}).extra(order_by=['test']) 
    
    +0

    -1:何が行われているか、どのようなものと互換性があるかなどを説明します。 –