Django-多个字段搜索问题 [英] Django - multiple field search issues

查看:50
本文介绍了Django-多个字段搜索问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试构建一个相对简单的搜索表单,该表单允许用户搜索三个搜索字段之一或三个搜索字段的任意组合.结果应根据给定的条件过滤查询集.这是我来自search_form.html的表格:

I am trying to build a relatively simple search form that allows the user to search one of three search fields or any combination of the three. The result should filter the queryset based upon the terms given. Here is my form from 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"字段中链接到我的过滤器时,只要在表格中输入了一年,它就可以正常工作.如果year(我数据库中的一个整数字段)为空,则它将为int()的基数10:''引发ValueError无效的文字.

  1. When I built this with just the 'q' filed, it worked fine. When I chained in the 'yr' field to my filter, it works fine as long as there is a year entered into the form. If year (an integer field in my database) was empty, it would raise a ValueError invalid literal for int() with base 10: ''.

当我在"ct"字段中进行链接并尝试搜索所有字段时,出现错误:无法将关键字"cat_icontains"解析为字段.我可以将过滤器更改为(cat = ct),它可以正常工作,但是我应该能够在数据库的'cat'字段上使用_icontains.我确定我缺少一些基本的知识,我们将为您提供任何帮助.

When I chained in the 'ct' field, and try to search all fields, I get the error: Cannot resolve keyword 'cat_icontains' into field. I can change the filter to (cat=ct) and it works fine, but I should be able to use _icontains on the 'cat' field from my database. I'm sure I am missing something basic, any help is appreciated.

更新:这是我基于以下答案的当前解决方案,该解决方案可以搜索任意字段组合:

Update: Here is my current solution based on the answers below, that allows searching on any combination of fields:

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的方式来完成此搜索结果?

This seems to be a 'busy' way to solve this. Is there a more idiomatic/pythonic way of accomplishing this search result?

推荐答案

不保证用户将提交 q yr ct .您不能信任您的用户数据.如果用户未提交任何这些参数,我认为这将导致错误 KeyError

It is not guarenteed that a user will submit q, yr, and ct. You cannot trust your users data. If a user didn't submit any of those params i think it will result in an error KeyError

您可以使用 get

you could set default for these using get

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

还可以在找到每个参数时构建查询集.请记住,查询集是 laziy

Also you could build your queryset as each param is found. remember querysets are laziy

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

对于第二个问题,我相信这是与语法相关的 cat__icontains 2个下划线(而不是 filter(cat_icontains = ct),就像您在代码中一样)

for your second question, I believe, it is syntax related cat__icontains 2 underscores (instead of filter(cat_icontains=ct), like you have in your code)

这篇关于Django-多个字段搜索问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆