【问题标题】:Django Search in Models with 3 fieldsDjango 在具有 3 个字段的模型中搜索
【发布时间】:2021-06-07 00:37:37
【问题描述】:

我有搜索字段、关键字、cdate_start、cdate_end。 它们可以为空。我想要的是,如果输入了关键字,则获取结果中唯一包含关键字的结果。如果未输入关键字但输入了 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")

以上解决方案看起来不太好。我怎样才能为它创建这样的搜索?

【问题讨论】:

  • 你到底想要什么?您想要一个搜索栏来搜索对象吗?
  • 我想创建涵盖上述所有条件的过滤器。

标签: python django django-views django-filter


【解决方案1】:

您使用令人困惑的逻辑使您的任务变得更加困难(而且使用表单比手动清理所有这些数据要容易得多)。编写更简单的逻辑:

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 a 制作过滤器的好包(比你做的更容易使用)。

【讨论】:

    猜你喜欢
    • 2018-03-23
    • 2015-09-09
    • 1970-01-01
    • 2020-11-02
    • 2017-11-06
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多