2013-01-31 71 views
1

我試圖建立一個相對簡單的搜索表單,允許用戶搜索三個搜索字段中的一個或三個的任意組合。結果應根據給定的術語過濾查詢集。這是我從形式search_form.html:Django - 多個字段搜索問題

<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'字段連接到我的過濾器時,只要有一年輸入到表單中,它就可以正常工作。如果year(數據庫中的整數字段)爲空,則會以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}) 

這似乎是一個「忙」的方式來解決這個問題。是否有一種更符合慣用/ pythonic的方式來完成此搜索結果?

回答

4

不保證用戶將提交q,yrct。你不能相信你的用戶數據。如果用戶沒有提交任何這些則params的我認爲這將導致KeyError

,你可以使用get

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

你也可以建立自己的查詢集默認設置爲這些錯誤,因爲每個參數是發現。記得查詢集是laziy

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

關於第二個問題,我認爲,這是相關的(而不是filter(cat_icontains=ct),就像你在你的代碼有)cat__icontains 2下劃線語法

+0

這真的幫了我。我已經更新了我的問題以反映我最新的(不完美)解決方案。 –

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}) 
+0

謝謝,這對我有幫助。 –