我正在尝试自定义 django-filter
的 DateRangeFilter
。我已经有一个可用的过滤器,可以过滤一系列预设选项,例如过去或即将到来的 30 天。
它还具有用于过滤特定年份的工作选项,尽管是硬编码的,例如:
filters = {
...
),
"past_years_minus_1": lambda qs, name: qs.filter(
**{
"%s__year" % name: now().year - 1,
}
),
"past_years_minus_2": lambda qs, name: qs.filter(
**{
"%s__year" % name: now().year - 2,
}
),
我希望添加的是能够动态创建一系列单年选择,特定于正在过滤的模型/字段的现有实例。因此,如果从 2019 年开始有模型 A
的实例,那么 2019
和 2020
会有选项 - 但不会更早,但是对于模型 B
会有选项如果适用,2014
起。
我创建了一个 __init__
覆盖来确定所需的年份并适当地扩展选项和过滤器(在本例中为 2017、2018、2019 和 2020)。
def __init__(self, *args, **kwargs):
""" Create filter options for every year of the span of years of the corresponding model instances """
""" Pass in model as class, field as str """
model = kwargs.pop("model", None)
field = kwargs.pop("field", None)
super(OrderDateRangeFilter, self).__init__(*args, **kwargs)
if model and field:
earliest_obj = model.objects.earliest()
earliest_year = getattr(earliest_obj, field).year
current_year = dt.date.today().year
range_of_years = [
earliest_year + i
for i in range(current_year - earliest_year)
if earliest_year + i <= current_year
]
range_of_years.reverse()
for year in range_of_years:
self.choices.append((f"{year}", _(f"{year}")))
self.filters[f"{year}"] = lambda qs, name: qs.filter(
**{
"%s__year" % name: year,
}
)
添加的选项按预期呈现(检查 select
小部件):
<option value="2020">2020</option>
<option value="2019" selected>2019</option>
<option value="2018">2018</option>
<option value="2017">2017</option>
url 查询字符串反映了所需的选择:
...&date_delivery_scheduled=2019&client=...
但是底层过滤器并没有像我预期的那样执行:返回的结果总是只针对第一年(2017 年),无论选择什么年份,并且通过 django-debug-toolbar
报告的底层 SQL 显示 {{ 1}} 最终构建了一个只返回第一年的查询:
django-filter
正如我所说,如果我对过滤器进行硬编码(例如明确针对“2018”等,或者作为过滤器定义中 SELECT ••• FROM "sales_order" WHERE "sales_order"."date_delivery_scheduled" BETWEEN '2017-01-01'::date AND '2017-12-31'::date
的一系列偏移量,则没有问题。它只是添加来自 now()
的过滤器,语法相同,但存在问题。
非常欢迎任何想法