2017-12-07 6 views
0

DRF 3でListViewを作成しました。データベース構造が複雑なため、カスタムクエリ、つまりデータを取得するための生のクエリを作成しました。しかし、データサイズが膨大なので、ロードするには多くの時間がかかります。ですから、ページネーションを実装する必要があります。以下はコードです。カスタムApiview結果データのページ番号をDRFに追加する方法

class SubnetList(APIView): 

    def get(self, request, format=None): 
     subnet_list = get_subnet_details(None) 
     return Response(subnet_list, status=status.HTTP_200_OK) 

    def get_subnet_details(subnet_id=None): 
     if subnet_id: 
      subnets = Subnet.objects.filter(id=subnet_id).values() 
     if not subnets: 
      raise Http404  
     else: 
      subnets = Subnet.objects.values() 

     subnet_list = [] 
     subnet_option_query = ' SELECT ' \ 
           ' options_value.id as value_id,' \ 
           ' options_value.content,' \ 
           ' options_option.id,' \ 
           ' options_option.name' \ 
           ' FROM subnets_subnetoption' \ 
           ' INNER JOIN subnets_subnet ON (subnets_subnetoption.subnet_id = subnets_subnet.id)' \ 
           ' INNER JOIN options_value ON (subnets_subnetoption.value_id = options_value.id)' \ 
           ' INNER JOIN options_option ON (options_value.option_id = options_option.id)' \ 
           ' INNER JOIN options_scope ON (options_option.scope_id = options_scope.id)' \ 
           ' WHERE subnets_subnetoption.subnet_id = %s ' 

     try: 
      for subnet in subnets: 
       subnet_dictionary = collections.OrderedDict() 
       subnet_dictionary['subnet_id'] = str(subnet['id']) 
       subnet_dictionary['name'] = str(subnet['name']) 
       subnet_dictionary['base_address'] = str(subnet['base_address']) 
       subnet_dictionary['bcast_address'] = str(subnet['bcast_address']) 
       subnet_dictionary['bits'] = str(subnet['bits']) 
       subnet_dictionary['begin'] = str(subnet['base_address']) 
       subnet_dictionary['end'] = str(subnet['bcast_address']) 
       subnet_dictionary['parent_id'] = str(subnet['parent_id']) 
       subnet_dictionary['vlan_common_name'] = str(subnet['vlan_common_name']) 
       subnet_dictionary['admin'] = str(subnet['admin']) 
       subnet_dictionary['responsible'] = str(subnet['responsible']) 
       subnet_dictionary['comments'] = str(subnet['comments']) 

       super_subnet = 'True' if subnet['is_physical'] else 'False' 
       subnet_dictionary['is_physical'] = super_subnet 
       options = SubnetOption.objects.raw(subnet_option_query % (subnet['id'])) 

       physical_attributes = collections.OrderedDict() 
       range_attributes = collections.OrderedDict() 
       gatewaydevice_attributes = collections.OrderedDict() 
       securityzone_attributes = collections.OrderedDict() 
       for option in options: 
        if option.name.lower() == 'provider': 
         subnet_dictionary['provider'] = str(option.value_id) 
        elif option.name.lower() == 'customer': 
         subnet_dictionary['customer'] = str(option.value_id) 
        elif option.name == 'Allocated by RIPE/ARIN/APNIC': 
         subnet_dictionary['allocated_by'] = str(option.value_id) 

        if super_subnet == 'True': 
         if option.name.lower() == 'vlan usage': 
          physical_attributes['vlan_usage'] = str(option.value_id) 
         elif option.name.lower() == 'environment': 
          physical_attributes['environment'] = str(option.value_id) 
         elif option.name.lower() == 'status': 
          physical_attributes['status'] = str(option.value_id) 
         elif option.name.lower() == 'vrf': 
          physical_attributes['vrf'] = str(option.value_id) 
         elif option.name.lower() == 'dns on demand status': 
          physical_attributes['dns_on_demand_status'] = str(option.value_id) 

         dmz = 'True' if subnet['dmz'] else 'False' 
         physical_attributes['dmz'] = dmz    
     except ValueError as e: 
      print(e) 
      pass 
     return subnet_list 
+1

、私はそれを修正しようとしました。 'subnet_list'が空のリストであるとき、それを返す点は何ですか?また、 'get_subnet_details(None)'を呼び出すことは意味がありません。実際の 'subnet_id'は決して通過することはなく、' None'を渡すことは必要ではないことを意味します。 – cezar

答えて

1

カップルより多くのパラメータを渡す(あなたがしたい場合は、それらをオプションにすることができます) - pagepagesizeのようなもの。次に、それらを使用してクエリを制限します。 MySQLの場合はLIMIT (pagesize * page),pageのようになります。ただし、詳細はデータベースエンジンによって異なります。

したがって、は、Django ORMを使用します。私はモデルを見ずに確かに言うことはできませんが、私はあなたが簡単なDjangoのORMのクエリとしてクエリを書き直すことができますかなり確信:

SubnetOption.objects.filter(subnet=subnet['id'])

と自動的に通ってくる必要があり、様々なINNERが加わります。

クエリの最後に[page*pagesize:(page+1)*pagesize]という範囲の行を使用すると、Djangoはその値をデータベースエンジンのLIMITまたは同等のものに変換します。

+0

返信ありがとうございました 私は余分なパラメータを追加しましたか?ページ= をURLに入れて、リクエストメタパラメータで同じものを取得しています。その値はクエリの範囲行に使用されます。したがって、私の問題を解決しました:) – Anish

-1

まず、アプリケーションにpagination.pyという名前のファイルを作成します。そして、これらのコードをコピーします。その後

class LargeResultsSetPagination(PageNumberPagination): 
    page_size = 1000 
    page_size_query_param = 'page_size' 
    max_page_size = 10000 

class StandardResultsSetPagination(PageNumberPagination): 
    page_size = 100 
    page_size_query_param = 'page_size' 
    max_page_size = 1000 

を、あなたは以下の例のように、これらのクラスから使用することができます。インデントが間違っていた

class BillingRecordsView(generics.ListAPIView): 
    queryset = Billing.objects.all() 
    serializer_class = BillingRecordsSerializer 
    pagination_class = LargeResultsSetPagination 
+0

彼はListAPIViewではなく、APIビューを使用しています。これは彼の場合には当てはまりません。 –

関連する問題