提问人:Michael Romanov 提问时间:10/25/2023 更新时间:10/29/2023 访问量:61
如何在 Django 过滤器中将 queryset 或 kwarg 传递给 RangeFilter 类
how to pass queryset or kwarg to RangeFilter class in Django filters
问:
我正在开发一个 Django 驱动的网站,该网站使用 django 过滤器,特别是 RangeFilter 来显示房地产的价格,并将其可视化为搜索表单上的滑块。
我的查询集最初在 PropertyListView 中形成为具有特定状态(销售或租赁)的对象列表,然后将其传递给筛选器 PropertyFilter。
PropertyFilter 使用其他几个类来构造相应的小部件,例如价格的滑块:
class PropertyFilter(FilterSet):
price = PriceFilter()
...
class PriceFilter(RangeFilter):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
values = [p.price for p in Property.objects.all()]
min_value = min(values)
max_value = max(values)
self.extra['widget'] = CustomRangeWidget(attrs={'label':_('Price, €'),'data-range_min':min_value,'data-range_max':max_value})
问题在于 PriceFilter 不“知道”查询集中有哪些对象,而是从完整的对象列表中获取价格通道。这导致了尴尬的滑块,其直径太宽,从 600 到 300,000 欧元,这无关紧要。
我想让 PriceFilter 从查询集中获取价格。怎么可能做到呢?我尝试直接在此过滤器中使用查询集,将查询集传递到其中,或将状态作为 kwarg 参数传递,但每次我都遇到错误。
请帮帮我,我被困住了。
答:
1赞
Kiarash Gh
10/25/2023
#1
您可以修改该类以接受 QuerySet,并使用它来确定价格范围PriceFilter
class PriceFilter(RangeFilter):
def __init__(self, queryset=None, *args, **kwargs):
super().__init__(*args, **kwargs)
if queryset is not None:
values = [p.price for p in queryset]
min_value = min(values) if values else 0
max_value = max(values) if values else 0
self.extra['widget'] = CustomRangeWidget(attrs={'label': _('Price, €'), 'data-range_min': min_value, 'data-range_max': max_value})
else:
self.extra['widget'] = CustomRangeWidget(attrs={'label': _('Price, €'), 'data-range_min': 0, 'data-range_max': 0})
然后,将查询集从 your 传递给 ,然后传递给 :PropertyListView
PropertyFilter
PriceFilter
class PropertyFilter(FilterSet):
price = PriceFilter(queryset=Property.objects.none()) # initialize with an empty queryset
def __init__(self, data=None, queryset=None, *args, **kwargs):
if queryset is not None:
self.price = PriceFilter(queryset=queryset, *args, **kwargs)
super().__init__(data, queryset, *args, **kwargs)
# other filters
class Meta:
model = Property
fields = ['price', ...]
现在,您可以在 QuerySet 中将查询集传递给:PropertyListView
PropertyFilter
class PropertyListView(ListView):
model = Property
def get_queryset(self):
queryset = Property.objects.filter(status='your_status_goes_here')
return queryset
def get_context_data(self):
context = super().get_context_data(**kwargs)
property_filter = PropertyFilter(data=self.request.GET, queryset=self.get_queryset())
context['filter'] = property_filter
return context
这样,将仅考虑筛选的查询集中的价格,确保滑块反映适当的价格范围。PriceFilter
我希望这对你有所帮助。
评论
0赞
Michael Romanov
10/25/2023
谢谢你,Kiarash!我以为我已经尝试过这种方法,但我可能会做错什么。现在我会再试一次,完全按照你的计划,并报告它是否有效。
0赞
Michael Romanov
10/25/2023
你接近工作!PriceFilter 现在从 PropertyFilter 获取查询集。但是现在我需要 PropertyFilter 从 PropertyListView 获取查询集,而不是生成它。你能告诉我怎么做吗?我正在尝试,但仍然收到错误(目前PropertyFilter.__init__()为参数“queryset”提供了多个值)。
0赞
Michael Romanov
10/26/2023
根据逻辑,PropertyFiltes 应从 PropertyListView 获取查询集。但是我不知道如何访问它。当我编写 price = PriceFilter(queryset=self.kwargs['queryset']) 时,我收到错误“name 'self' is not defined”。请帮忙!
1赞
Kiarash Gh
10/27/2023
为此,您应该修改类以接受 from 并将其传递给类PropertyFilter
queryset
PropertyListView
PriceFilter
1赞
Kiarash Gh
10/27/2023
我已经编辑了答案,希望这对:)有所帮助
评论