2017-06-07 6 views
1

django_filterとextentionでDjango Rest Framework(DRF)の値のリストによるフィルタリングがあまりにも複雑になるのは間違いですか?具体的にdjango_filter Django Rest Framework(DRF)の処理query_params get vs getlist

、我々は先験的「GETLIST」ではなく、私たちは以下のようなURLを経由して提出した多値パラメータを処理するときに「取得」で扱われるべきパラメータを指定する必要があります

http://example.com?country=US&country=CN

今、我々はこの要求を処理し、

request.query_params.get( '国')Rながらならびにrequest.query_params [ '国']が誤っ 'CN' を戻しますequest.query_params.getlist( 'country')は、この例では['US'、 'C​​N']を返します。

は、だから私は現在、やる、これを処理するために:

だから私の現在のロジックは、私は、この透過処理する内部方法を知らないと私は、パラメータが複数の値を指定している可能性が事前に指定しなければならないことを指示しますこのような何か(簡単のためなど、フィルタリング、すべての実際の要求処理をスキップ):

理論的には
class CountryFilter(filters.FilterSet): 
    """ placeholder: this is a separate question as to why I can't get any of these to work as desired. """ 
    #country = filters.CharFilter(method='filter_country') 
    #country = filters.CharFilter(name='country', lookup_expr='in') 
    #country = filters.MultipleChoiceFilter() 

class CountryViewSet(viewsets.ModelViewSet): 
    """Viewset to work with countries by ISO code""" 

    def list(self, request, *args, **kwargs): 
     """do something based on a request for one or more countries 
     such as http://example.com?country=CA&country=CN&country=BR 
     """ 
     query_params = request.query_params 
     filter0 = CountryFilter(query_params, queryset=Country.objects.all())  

     # if filter0 worked, we'd be done and wouldn't need below 
     # but it doesn't 

     query_dict = {} 
     params_to_list = ['country', 'another_param'] 
     for k in query_params.keys(): 
      if k in params_to_list: 
       query_dict[k] = query_params.getlist(k) 
      else: 
       query_dict[k] = query_params.get(k) 

     # use the newly counstructed query_dict rather than query_params 
     filter1 = CountryFilter(query_dict, queryset=Country.objects.all()) 

     import pdb; pdb.set_trace() 
     return HttpResponse('ok') 

、フィルタ1は、望ましい結果filter0はありませんが、私に与える必要があります。

これに基づくコードは本番環境では機能しますが、有効なリストを文字列に戻すなどのいくつかの効果があります。私はここでその質問にドリフトしたくありません。これが人の行為であるかどうかは疑問です。具体的に

答えて

0

、我々は先験的「GETLIST」ではなく、私たちは以下のようなURLを経由して提出した多値パラメータを処理するときに「取得」で扱われるべきパラメータを指定する必要があります

これは必要ではありません。 Filterインスタンスは、フォームパラメータフィールドを作成し、フォームフィールドはクエリパラメータの検証を実行します。これらのフィールドは標準のDjangoフォームフィールドで、ウィジェットは、クエリdictから値を抽出するときに.getlist()または.get()を使用するかどうかを決定します。クエリdictを前処理する必要はありません。

QueryDict('a=1&a=2')は機能的にSelectMultipleウィジェットのdict(a=['1', '2'])と同等であるため、filter0とfilter1は実際には同じように動作するはずです。その.value_from_datadict()は、前者の場合は.getlist()、後者の場合は.get()を呼び出します。どちらも値のリストを返します。


複数の値によるフィルタリングの問題を解決するには、2つの方法があります。

  1. MultipleChoiceFilterdocs
  2. CSVベースのフィルタ(docs)を使用し

複数選択フィルタは、選択、複数のウィジェットをレンダリングし、?a=1&a=bのようなクエリ文字列を期待し使用してください。上記の操作を試みましたが、choicesは省略されました。選択なしでは、html selectはオプションなしでレンダリングされ、その後は検証が失敗します(入力を検証するために同じオプションを使用するため)。あるいは、ModelMultipleChoiceFilterを使用することができます。querysetから選択肢を構成する必要があります。クエリーセット/選択処理は、基本となるフォームフィールドの振る舞いに組み込まれており、django-filterに特有のものではないことに注意してください。

後者のオプションについては、上記のドキュメントに詳細がありますが、テキスト入力をレンダリングし、?a=1&a=2の代わりに?a=1,2のようなクエリ文字列が必要です。

関連する問題