1

ユーザーが3つの検索フィールドの1つ、または3つの任意の組み合わせを検索できる比較的単純な検索フォームを作成しようとしています。結果は、指定された用語に基づいてクエリセットをフィルタリングする必要があります。これがsearch_form.htmlからの私のフォームです:

<form class="form-horizontal" action="/search/" method="get">
    <legend>Generate a Quiz:</legend>
    <div class="control-group">
        <label class="control-label" for="q">Search term</label>
        <div class="controls">
            <input type="text" name="q" placeholder="Search term" autocomplete="on"/>
        </div>
    </div>  
    <div class="control-group">
        <label class="control-label" for="yr">Year</label>
        <div class="controls">
            <input type="text" name="yr" placeholder="Year" autocomplete="on"/>
        </div>
    </div>  
    <div class="control-group">
        <label class="control-label" for="ct">Category</label>
        <div class="controls">
            <input type="text" name="ct" placeholder="Category" autocomplete="on"/>
        </div>
    </div>  
    <div class="controls">
        <button type="submit" class="btn btn-primary">Fetch  &raquo;</button>
    </div>          
</form>

そして、これが私の見解です:

def search(request):
    error = False
    if 'q' in request.GET:
        q = request.GET['q']
        yr = request.GET['yr']
        ct = request.GET['ct']
        if not ((q or yr) or ct):
            error = True
        else:
            question_set = Uroquiz.objects.filter(question__icontains=q).filter(year=yr).filter(cat_icontains=ct)
            paginator = Paginator(question_set, 1)
            page = request.GET.get('page')

            try:
                question_set = paginator.page(page)
            except PageNotAnInteger:
                question_set = paginator.page(1)
            except EmptyPage:
                question_set = paginator.page(paginator.num_pages)
            return render_to_response('search_results.html',
                {'question': question_set, 'query': q, 'year': yr, 'ct': ct})
    return render_to_response('search_form.html', {'error': error})

問題:

  1. 'q'だけをファイルしてこれを作成したところ、正常に機能しました。'yr'フィールドをフィルターにチェーンすると、フォームに年が入力されている限り、正常に機能します。年(私のデータベースの整数フィールド)が空の場合、基数10のint()に対してValueError無効なリテラルが発生します:''。

  2. 'ct'フィールドにチェーンして、すべてのフィールドを検索しようとすると、エラーが発生します:キーワード'cat_icontains'をフィールドに解決できません。フィルタを(cat = ct)に変更すると正常に機能しますが、データベースの「cat」フィールドで_icontainsを使用できるはずです。私は基本的な何かが欠けていると確信しています、どんな助けでもありがたいです。

更新:以下の回答に基づく現在のソリューションは、フィールドの任意の組み合わせで検索できるようにするものです。

def search(request):
    q = request.GET.get('q')
    yr = request.GET.get('yr', 0)
    ct = request.GET.get('ct')
    question_set = Uroquiz.objects.all()

    if q:
        if not (yr or ct):
            question_set = Uroquiz.objects.filter(question__icontains=q)
    if yr:
        if not (q or ct):
            question_set = Uroquiz.objects.filter(year=yr)
    if ct:
        if not (q or yr):
            question_set = Uroquiz.objects.filter(cat__icontains=ct)
    if (q and yr):
        if not ct:
            question_set = Uroquiz.objects.filter(question__icontains=q).filter(year=yr)
    if (q and ct):
        if not yr:
            question_set = Uroquiz.objects.filter(question__icontains=q).filter(cat__icontains=ct)
    if (yr and ct):
        if not q:
            question_set = Uroquiz.objects.filter(year=yr).filter(cat__icontains=ct)
    if ((q and yr) and ct):
        question_set = Uroquiz.objects.filter(question__icontains=q).filter(year=yr).filter(cat__icontains=ct)
    if not ((q or yr) or ct):
        return render_to_response('search_form.html')
    paginator = Paginator(question_set, 1)
    page = request.GET.get('page')
    try:
        question_set = paginator.page(page)
    except PageNotAnInteger:
        question_set = paginator.page(1)
    except EmptyPage:
        question_set = paginator.page(paginator.num_pages)
    return render_to_response('search_results.html',
        {'question': question_set, 'query': q, 'yr': yr, 'ct': ct})

これは、これを解決するための「忙しい」方法のようです。この検索結果を達成するためのより慣用的/Python的な方法はありますか?

4

2 に答える 2

4

qユーザーが、、、yrおよびを送信することは保証されていませんct。ユーザーデータを信頼することはできません。ユーザーがこれらのパラメータのいずれも送信しなかった場合、エラーが発生すると思いますKeyError

これらのデフォルトを使用して設定できますget

    q = request.GET.get('q')
    yr = request.GET.get('yr', 0)
    ct = request.GET.get('ct')

また、各パラメータが見つかったときにクエリセットを作成することもできます。クエリセットは怠惰であることを忘れないでください

question_set = Uroquiz.objects.all()    
q = request.GET.get('q')
if q:
  question_set = question_set.filter(question__icontains=q)
etc

2番目の質問については、構文に関連するcat__icontains2つのアンダースコアです(filter(cat_icontains=ct)コードのようにではなく)

于 2013-01-31T13:46:43.290 に答える
1
def search(request):
    q, yr, ct = "", "", ""
    question_set = Uroquiz.objects.filter()

    if request.GET.get('q'):
        question_set = question_set.filter(question__icontains=q)

    if request.GET.get('yr'):
        question_set = question_set.filter(year=yr)

    if request.GET.get('ct'):
        question_set = .filter(cat__icontains=ct)

    paginator = Paginator(question_set, 10)

    try:
        page = int(request.GET.get('page', '1'))
    except ValueError:
        page = 1

    try:
        question_set = paginator.page(page)
    except (EmptyPage, InvalidPage):
        question_set = paginator.page(paginator.num_pages)

    return render_to_response('search_results.html',
        {'question': question_set, 'query': q, 'year': yr, 'ct': ct})
于 2013-01-31T13:50:11.093 に答える