2016-02-01 217 views
1

我正在尝试在我的网站上进行过滤关键字的搜索精简程序,问题是有时候人们可能想要搜索多个关键字。问题是默认情况下,如果他们输入“hello world”,它会搜索完整的短语,但我希望它将它分开,以便搜索“hello”和“world”。到目前为止,我已将.split()添加到关键字,并将它分开,但它阻止了我在查询中使用__icontains。任何人都可以提出最好的方法来做到这一点?干杯!过滤多个关键字

代码 -

def browse(request): 

    business_industry = request.GET.get('business_industry', '') 
    business_address_region = request.GET.get('business_address_region', '') 
    employment_type = request.GET.get('employment_type', '') 
    pay_rate = request.GET.get('pay_rate', '') 
    keywords = request.GET.get('keywords', '').split() 

    form = JobSearchForm(initial=request.GET) 

    filters = Q(active_listing=True) 

    if business_industry: 
     filters &= Q(business_industry=business_industry) 
    if business_address_region: 
     filters &= Q(business_address_region=business_address_region) 
    if employment_type: 
     filters &= Q(employment_type=employment_type) 
    if pay_rate: 
     filters &= Q(pay_rate=pay_rate) 
    if keywords: 
     filters &= Q(job_description__icontains=keywords) | Q(job_title__icontains=keywords) 

    job_listings = JobListing.objects.filter(filters).distinct().order_by('-listing_date') 

    context_dict = { 
     'joblistings': job_listings, 
     'form': form 
    } 

    return render(request, 'browse.html', context_dict) 

编辑: 我被要求解释为什么这个帖子是独一无二的,其他的问题是询问如何查询自己比较他所有的模型字段。这是要求如何从单个字段过滤多个关键字。

+0

的可能的复制[如何获得Django的过滤器icontains多个字段(http://stackoverflow.com/questions/15045101/如何对获得-更比一个场与 - Django的过滤icontains)。它不完全相同,但本质上是:手动循环。 – dhke

回答

2

可以使用Reduce函数:

reduce(lambda x, y: x | y, [Q(name__icontains=word) for word in list]) 

更改此代码:

if keywords: 
    filters &= Q(job_description__icontains=keywords) | Q(job_title__icontains=keywords) 

要:

if keywords: 
    fliters &= reduce(lambda x, y: x | y, [Q(job_description__icontains=word) for word in keywords]) | reduce(lambda x, y: x | y, [Q(job_title__icontains=word) for word in keywords]) 

,只要你喜欢,你可以改变拉姆达的定义。例如,如果您想查找包含所有关键字的列表,请将lambda x, y: x | y替换为lambda x, y: x & y

编辑:因为有两个不必要的括号

修改后的代码
+0

这工作完美!最初,我被这个答案推翻了,纯粹是因为我没有足够的能力去理解减少功能,而且看起来非常困难。尽管如此,我尝试了代码,它完美无瑕,非常令人印象深刻。谢谢! –

+0

谢谢,'reduce'是一个内置函数,你可以在这里阅读(https://docs.python.org/2/library/functions.html#reduce) –

2

您可以在一个循环中查询过keywords

job_description_q = Q() 
for keyword in keywords: 
    job_description_q |= Q(job_description__icontains=keyword) 
filters &= job_description_q 

而对于jobtitle类似的循环。

+0

这有一种解决我的问题,而代码的作品它确实有问题。它寻找任何具有任何关键字的列表,我希望它找到具有所有关键字的列表。你会知道如何修改它吗? –

+0

您可以在循环中使用'&='而不是'| ='。 – nima

1

您可能需要使用迭代这个

keyword_filter = Q() 
for keyword in keywords: 
    keyword_filter|=Q(job_description__icontains=keyword) | Q(job_title__icontains=keyword) 
filters &= keyword_filter 

您可以在这个类似的问题,看看https://stackoverflow.com/a/5956422/2599266

+0

这有一种解决我的问题,而代码的作品它确实有问题。它寻找任何具有任何关键字的列表,我希望它找到具有所有关键字的列表。你会知道如何修改它吗? –

0
filters = {'active_listing':True} 
q = Q() 

if business_industry: 
    filters['business_industry'] = business_industry 
if business_address_region: 
    filters['business_address_region'] = business_address_region 
if employment_type: 
    filters['employment_type'] = employment_type 
if pay_rate: 
    filters['pay_rate'] = pay_rate 
if keywords: 
    q = Q(job_description__icontains=keywords) | Q(job_title__icontains=keywords) 

job_listings = JobListing.objects.filter(q, **filters).distinct().order_by('-listing_date')