0

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 に追加されているように見え、期待どおり、フィールドに指定されたフィールド値を含むページが返されます。ただし、すべてのフィールドが空白のままの場合は、結果を返すこともエラーを生成することもありません。

私は明らかに何かが欠けていますが、私の人生では何がわからないのですか。他の誰かがこの問題に遭遇しましたか?

4

1 に答える 1

1

検索ビューをデバッグしているときに、リストされているすべてのフィールドが実際にはフォームにあったとしても、最初のif条件が 1 つのフィールドに対してrequest.GETのみ返されることがわかりました。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上記の名前を に変更すると、ページネーションに関する Django ドキュメントresults_listのコードをビューにプラグインできます。私が見つけた1つの警告は、検索文字列を含む新しい変数を追加し、それをページネーションリンクの前に含める必要があることです。そうしないと、定義されている「次へ」または「前へ」のリンクをクリックすると検索フォームに戻りますドキュメントで。

最後に、Django の ModelForm クラスに依存するのではなく、HTML でフォームを作成すると、最もうまく機能するようです。そうすれば、フォームの検証エラーをデバッグしようとして頭を悩ませる必要がなくなり、ビュー関数内で独自の検証ルールを定義できます。

于 2012-04-29T17:54:34.237 に答える