[英]Django Search in Models with 3 fields
我有搜索字段、關鍵字、cdate_start、cdate_end。 它們可以是 null。 我想要的是,如果輸入了關鍵字,則獲取結果中唯一包含關鍵字的結果。 如果未輸入關鍵字但輸入了 cdate_start,則僅獲取大於此 cdate_start 的項目。 或輸入關鍵字和 cdate_end 然后獲取項目僅包含此關鍵字且少於 cdate_end 等。我必須獲取所有這樣的組合。 我嘗試過這樣的事情。
if self.request.GET.get('feedback_s_keyword') is not None:
keyword = self.request.GET.get('feedback_s_keyword')
else:
keyword = ''
name_or = Q(author__name__icontains=keyword)
surname_or = Q(author__surname__icontains=keyword)
feedback_or = Q(feedback__icontains=keyword)
if self.request.GET.get('feedback_s_cdate_start') is not None:
cdate_start = self.request.GET.get('feedback_s_cdate_start')
cdate_start = cdate_start.split('/')
try:
year_s = cdate_start[0]
month_s = cdate_start[1]
day_s = cdate_start[2]
except:
year_s = 2001
month_s = 1
day_s = 1
else:
year_s = 2001
month_s = 1
day_s = 1
cdate_gte = Q(cdate__gte=datetime.date(year_s, month_s, day_s))
if self.request.GET.get('feedback_s_cdate_end') is not None:
cdate_end = self.request.GET.get('feedback_s_cdate_end')
cdate_end = cdate_end.split('/')
try:
year_e = cdate_end[0]
month_e = cdate_end[1]
day_e = cdate_end[2]
except:
year_e = 3000
month_e = 12
day_e = 31
else:
year_e = 3000
month_e = 12
day_e = 31
cdate_lte = Q(cdate__lte=datetime.date(year_e, month_e, day_e))
feedbacks = Feedback.objects.filter(name_or | surname_or | feedback_or | cdate_gte | cdate_lte).order_by(
"-cdate")
但是,當然,如果沒有輸入 cdate,它會返回所有內容。 我想我可以設置一些標志,比如keyword_entered =True、feedback_s_cdate_start_entered=True、feedback_s_cdate_end_entered=True並編寫多個 if 條件並根據這些標志生成過濾器。
if keyword_entered and not feedback_s_cdate_start_entered and not feedback_s_cdate_end_entered:
feedbacks = Feedback.objects.filter(name_or | surname_or | feedback_or ).order_by(
"-cdate")
elif keyword_entered and feedback_s_cdate_start_entered and not feedback_s_cdate_end_entered:
feedbacks = Feedback.objects.filter(name_or | surname_or | feedback_or | cdate_gte).order_by(
"-cdate")
上述解決方案看起來不太好。 我怎樣才能創建這樣的搜索呢?
您使用的令人困惑的邏輯使您的任務變得更加困難(而且使用表單比手動清理所有這些數據要容易得多)。 編寫更簡單的邏輯:
from datetime import datetime
filters = []
keyword = self.request.GET.get('feedback_s_keyword')
if keyword is not None:
name_contains = Q(author__name__icontains=keyword)
surname_contains = Q(author__surname__icontains=keyword)
feedback_contains = Q(feedback__icontains=keyword)
filters.append(name_contains | surname_contains | feedback_contains)
cdate_start = self.request.GET.get('feedback_s_cdate_start')
if cdate_start is not None:
start_date = datetime.strptime(cdate_start, '%Y/%m/%d')
filters.append(Q(cdate__gte=start_date))
# Any more filters
feedbacks = Feedback.objects.filter(*filters)
# filter(*filters) would mean something like `filter(q1, q2, q3)` meaning they would be ANDed.
# You can OR them by using functools.reduce(operator.or_, filters)
注意:與其手動執行所有這些操作,不如使用django-filter一個很棒的 package 來制作過濾器(比你做的更容易使用)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.