2009-07-10 13 views
5

私はこのモデルがあります:モデル検索フォームを作成する最も良い方法は?

class Aircraft(models.Model): 
    model  = models.CharField(max_length=64, blank=True) 
    type  = models.CharField(max_length=32) 
    extra  = models.CharField(max_length=32, blank=True) 
    manufacturer = models.CharField(max_length=32) 
    engine_type = models.IntegerField("Engine Type", choices=ENGINE_TYPE, default=0) 
    cat_class = models.IntegerField("Category/Class", choices=CAT_CLASSES, default=1) 

をそして私は、ユーザーが彼らの基準を満たすすべての航空機を見つけるために使用されるデータを入力することができますフォームが表示され、「航空機を見つける」のページを持っています。たとえば、ユーザーはテキストボックスに「boeing」と入力し、engine_typeボックスに「jet」を入力すると、データベースにすべてのboeingジェットが表示されます。私は今これをやっている方法は、このフォームである:

class AircraftSearch(ModelForm): 
    search = forms.CharField(max_length=100, required=False) 
    class Meta: 
     model = Aircraft 
     fields = ('engine_type', 'cat_class',) 

そしてAircraft.objects.all()に追加されますfilter()年代のセットには、このフォームからのデータを変換する(不コンプレックス)ビュー。 (CharFieldごとに4つの検索フィールドを用意するのではなく、すべてを1つの検索フィールドにまとめました)。

これはすべて問題なく動作します。ユーザーが検索条件からエンジンタイプを除外したい場合は、「Any」がエンジンタイプフィールドの有効な選択肢ではないため、それらはうまくいきません。エンジンの種類とカテゴリ/クラスの新しいフィールド/ウィジェットを作成して、「Any」を含むようにしなければなりません。

私は好奇心が強いです。より良い方法がありますか?これはすでに他の誰かに取り組まれてきた非常に一般的な作業のようですが、Google検索では何も出ません。

答えて

8

機能的には、フィルタリングでその特定の検索ベクトルを含まないだけで、「任意」が達成されます。

通常、ModelFormはモデルの作成と編集用です。この場合には、私はあなたの普通の形をしているよりもはるかに多くを助けることだかわからない:フィールドが空でないとき

class AircraftSearch(forms.Form): 
    search = forms.CharField(max_length=100, required=False) 
    engine_type = forms.ChoiceField(choices=ENGINE_TYPE) 
    cat_class = forms.ChoiceField(choices=CAT_CLASS) 

検索を行うには、そしてちょうどフィルタリング:

def search(request): 
    if request.method == 'POST': 
     results = Aircraft.objects.all() 

     search = request.POST.get('search', None) 
     if search: 
      results = results.filter(Q(model=search)|Q(type=search)|Q(extra=search)|Q(manufacturer=search)) 

     engine_type = request.POST.get('engine_type', None) 
     if engine_type: 
      results = results.filter(engine_type=engine_type) 

     cat_class = request.POST.get('cat_class', None) 
     if cat_class: 
      results = results.filter(cat_class=cat_class) 

     return render_to_response('aircraft.html', {'form': AircraftSearch(request.POST), 'aircraft': results}) 

    return render_to_response('aircraft.html', {'form': AircraftSearch()}) 
+1

問題は、 'choices = ENGINE_TYPE'には「jet」や「piston」などの有効な選択肢だけが含まれ、「Any」ではないことです。そのオプションをENGINE_TYPEリストに追加するか、各SearchFormにオプションの1つが含まれていれば、特定のエンジンタイプでフィルタリングする必要があります。 ENGINE_TYPEリストに "Any"オプションを追加して検索フォームを作成するのは問題ではありませんが、それは私にはハック感があり、より良い "非ハッキー"メソッドが存在するならば、むしろそうするでしょう。 – priestc

+1

choices =(( ''、 'Any')、)+ ENGINE_TYPEのようなことをするのはかなりクリーンな修正だと思う。モデルに「any」は導入されませんが、フォームには使用可能です。 – tghw

3

私はあなたがModelFormを使うべきではないと思います。
典型的なModelForm usescaseはデータ操作であり、検索は行いません。

代わりに、必要なフィールドと、特定のフィールドの検索を無効にする(無効にする)チェックボックスを元に、完全に新しいフォームを作成します。
もちろん、ファイルをインポートしてそのリストを使用するだけで、モデルで定義された選択肢を使用する必要があります。

関連する問題