2016-02-01 425 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')