2012-04-23 7 views
0

私は、ModelFormクラスを使用して検索フォームを作成することを検討しています。これにより、単一のフィールドキーワード検索ではなく特定のフィールドでモデルの値を検索できます。私はまた、空のフィールドを無視したい。Django - 複数のフィールドとModelFormで検索を実行する方法

私はHaystackやDjapianなどの検索エンジンオプションを調べただけでなく、Djangoで手動で問題に近づいていますが、複数のフィールドでクエリを実行すると結果が返ってくるようには思えません。私はまた、ドキュメントから直接この複雑なクエリを試してみました

def search(request): 
    error = False 
    form = InfoForm() 
    if 'field1' or 'field2' or 'field3' in request.GET: 
     form = InfoForm(request.GET) 
     if form.is_valid(): 
      cd = form.cleaned_data 
      field1 = cd['field1'] 
      field2 = cd['field2'] 
      field3 = cd['field3'] 
      if not(field1 or field2 or field3): 
       error = True 
      else: 
       query = Q() 
       if request.GET['field1']: 
        query &= Q(field1__icontains=request.GET['field1']) 
       if request.GET['field2']: 
        query &= Q(field2__icontains=request.GET['field2']) 
       if request.GET['field3']: 
        query &= Q(field3__icontains=request.GET['field3']) 

       results = PersonInfo.objects.filter(query).distinct() 

       return render_to_response('search/personsearch.html', 
         {'query': query, 
         'field1': field1, 
         'field2': field2, 
         'field3': field3, 
         'results': results, 
         }, 
        context_instance=RequestContext(request)) 

    return render_to_response('search/infosearch.html', 
      {'error': error, 
      'form': form}, 
     context_instance=RequestContext(request)) 

この

は私が文書化されているものに加えて、部分的にこのサイト上のいくつかの類似した質問への回答に基づいて、これまでのビューのために持っているものです:いずれの場合も

query = InfoModel.objects.get(
    Q(field1__icontains=field1) | 
    Q(field2__icontains=field2) | 
    Q(field3__icontains=field3) 
) 

、クエリ文字列?field1=&field2=&field3=はURLに追加表示され、予想通りフィールドで与えフィールド値を持つページに戻ります。すべてのフィールドを空白のままにすると結果が返されたり、エラーが生成されることはありません。

私は明らかに何かが不足していますが、私の人生にとっては何が分かりませんか。他の誰かがこの問題に遭遇しましたか?

+0

問題を切り分ける必要があります。ビューに問題がありますか?またはクエリですか?あなたの2つのクエリの例は異なります。最初はAND、2番目はORです。 3つのORクエリで 'get 'すると、問題を尋ねています(複数の期待される結果の代わりにフィルタを使います)。私は、Pythonのデバッガに入れて、生成されたクエリで遊びます。 –

+0

それで...あなたはこれを最終的に解決しましたか? – mac

+0

はい、私は若干異なるアプローチをとっており、request.GETでトップレベルの 'field1 'の1つのフィールドのみをチェックしました.GETは:'完全な答えとして新しいコードを投稿します。面白い。 –

答えて

1

検索ビューをデバッグしている間、私はrequest.GETに対する初期if条件のみ記載されているすべてのフィールドがフォームで実際にあった場合でも、1つのフィールドのTrueを返されたことがわかりました。

そこから、私のマルチフィールド検索を実現する最も簡単な方法は、.filter()メソッドを一緒に文字列にすることでした。検索フォームの空のフィールドは、期待通りに無視されますが、すべてのフィールドが空白の場合は、適切に処理されたエラーで検索フォームに戻ります。

def search(request): 
    errors = [] 
    if 'field1' in request.GET: 
     field1 = request.GET['field1'] 
     field2 = request.GET['field2'] 
     field3 = request.GET['field3'] 
     if not ((field1 or field2) or field3): 
      errors.append('Enter a search term.') 
     else: 
      results = MyModel.objects.filter(
       field1__icontains=field1 
      ).filter(
       field2__icontains=field2 
      ).filter(
       field3__icontains=field3 
      ) 
      query = "Field 1: %s, Field 2: %s, Field 3: %s" % (field1, field2, field3) 
      return render_to_response('search/search_results.html', 
        {'results': results, 'query': query}) 
    return render_to_response('search/search_form.html', 
      {'errors': errors}) 

ここquery文字列は今、単にあなたがあなたのテンプレートにドロップすることができ、検索用語のフォーマットされたリストを返します。しかし、変数を直接返すこともできますし、必要に応じて変数を検索結果ページに配置することもできます。

ページネーションは、検索結果にもうまく機能し、実際のアプリケーションには不可欠です。上記のresultsの名前をresults_listに変更し、the Django documentation on Paginationのコードを表示することができます。私が見つけた1つの警告は、検索文字列を含む新しい変数を追加して、ページネーションリンクの前にその変数を含めるか、定義された「次」または「前の」リンクをクリックすると検索フォームに戻りますドキュメント内にあります。

最後に、DjangoのModelFormクラスに頼るのではなく、HTMLでフォームを構築すると最も効果的なようです。そうすれば、フォームの検証エラーをデバッグしようとして頭を抜かなくても、ビュー機能内で独自の検証ルールを定義することができます。

関連する問題