根据请求在 django-filter ModelChoiceFilter (select) 和 ModelMultipleChoiceFilter (multi-select) 菜单中自定义查询集
Customize queryset in django-filter ModelChoiceFilter (select) and ModelMultipleChoiceFilter (multi-select) menus based on request
我正在使用 django-filter in 2 places: My Django Rest Framework API, and in my FilterViews (Django Filter's Generic ListViews.) In the case of my FilterViews I'm showing both select boxes (ModelChoiceFilter) 和多个 select 框 (ModelMultipleChoiceFilter) 进行过滤。
我需要能够根据请求中的字段限制 select 和多 select 输入中的内容。
更改在 FilterSet 的相关字段中列为 kwarg 的内容相对简单。例如,这是我的 FilterSet,其中查询集设置为 kwarg:
class FieldFilter(django_filters.FilterSet):
"""Filter for the field list in the API"""
dataset = ModelChoiceFilter(queryset=Dataset.objects.all())
class Meta(object):
"""Meta options for the filter"""
model = Field
fields = ['dataset']
并且在 get_queryset()
方法中限制 结果 在 DRF 中的内容相对简单。例如,这是我的 DRF 视图集:
class FieldViewSet(viewsets.ReadOnlyModelViewSet):
"""A ViewSet for viewing dataset fields"""
queryset = Field.objects.all()
serializer_class = FieldSerializer
filter_class = FieldFilter
def get_queryset(self):
"""Get the queryset"""
queryset = super(FieldViewSet, self).get_queryset()
queryset = queryset.filter(
dataset__organization=self.request.organization)
return queryset
当显示视图时,我无法在任何地方编辑 filter_class
中的 Dataset
字段。
这在 Django FormView
通用视图中非常简单,但 FieldViewSet
似乎没有遵循与通用视图相同的 get_form()
结构。在管理员中也相对简单,但 DRF/Django-Filter 似乎也不遵循该结构。
有什么方法可以根据每个请求自定义这些输入中的查询集吗?最好同时在 FilterViews 和 HTML API 浏览器中,但如果对于 HTML API 浏览器来说太复杂了,那么只在 FilterViews 中就可以了。
我在寻找解决方案时也遇到了问题。
我(我认为)通过以下方式解决了它:
views.py
table_filter = ExampleFilter(request.GET, kwarg_I_want_to_pass=request.user, queryset=qs)
filters.py
class ExampleFilter(django_filters.FilterSet):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('kwarg_I_want_to_pass', None)
super(ExampleFilter, self).__init__(*args, **kwargs)
self.filters['field_to_filter'].extra.update({
'queryset': Supplier.objects.filter(related_user=self.user),
'empty_label': '',
'help_text': False
})
class Meta:
model = ExampleModel
fields = ['related_user', 'field_to_filter', ... other fields]
经过几个小时的搜索,我在官方文档中找到了解决方案here!
ModelChoiceFilter
和 ModelMultipleChoiceFilter
的查询集参数支持可调用行为。如果传递了一个可调用对象,它将以 request
作为唯一参数被调用。
import django_filters as filters
from django.utils.translation import gettext as _
def ourBranches(request):
if request is None:
return Branch.objects.none()
company = request.user.profile.company
return Branch.objects.filter(company=company)
class UnitFilter(filters.FilterSet):
branch = filters.ModelChoiceFilter(
queryset=ourBranches, empty_label=_("All Branches"))
class Meta:
model = Unit
fields = ('branch', )
并且在视图中,我确保也通过了 request
qs = Unit.objects.all()
filter = UnitFilter(self.request.GET, request=self.request, queryset=qs)
table = UnitTable(filter.qs)
我正在使用 django-filter in 2 places: My Django Rest Framework API, and in my FilterViews (Django Filter's Generic ListViews.) In the case of my FilterViews I'm showing both select boxes (ModelChoiceFilter) 和多个 select 框 (ModelMultipleChoiceFilter) 进行过滤。
我需要能够根据请求中的字段限制 select 和多 select 输入中的内容。
更改在 FilterSet 的相关字段中列为 kwarg 的内容相对简单。例如,这是我的 FilterSet,其中查询集设置为 kwarg:
class FieldFilter(django_filters.FilterSet):
"""Filter for the field list in the API"""
dataset = ModelChoiceFilter(queryset=Dataset.objects.all())
class Meta(object):
"""Meta options for the filter"""
model = Field
fields = ['dataset']
并且在 get_queryset()
方法中限制 结果 在 DRF 中的内容相对简单。例如,这是我的 DRF 视图集:
class FieldViewSet(viewsets.ReadOnlyModelViewSet):
"""A ViewSet for viewing dataset fields"""
queryset = Field.objects.all()
serializer_class = FieldSerializer
filter_class = FieldFilter
def get_queryset(self):
"""Get the queryset"""
queryset = super(FieldViewSet, self).get_queryset()
queryset = queryset.filter(
dataset__organization=self.request.organization)
return queryset
当显示视图时,我无法在任何地方编辑 filter_class
中的 Dataset
字段。
这在 Django FormView
通用视图中非常简单,但 FieldViewSet
似乎没有遵循与通用视图相同的 get_form()
结构。在管理员中也相对简单,但 DRF/Django-Filter 似乎也不遵循该结构。
有什么方法可以根据每个请求自定义这些输入中的查询集吗?最好同时在 FilterViews 和 HTML API 浏览器中,但如果对于 HTML API 浏览器来说太复杂了,那么只在 FilterViews 中就可以了。
我在寻找解决方案时也遇到了问题。
我(我认为)通过以下方式解决了它:
views.py
table_filter = ExampleFilter(request.GET, kwarg_I_want_to_pass=request.user, queryset=qs)
filters.py
class ExampleFilter(django_filters.FilterSet):
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('kwarg_I_want_to_pass', None)
super(ExampleFilter, self).__init__(*args, **kwargs)
self.filters['field_to_filter'].extra.update({
'queryset': Supplier.objects.filter(related_user=self.user),
'empty_label': '',
'help_text': False
})
class Meta:
model = ExampleModel
fields = ['related_user', 'field_to_filter', ... other fields]
经过几个小时的搜索,我在官方文档中找到了解决方案here!
ModelChoiceFilter
和 ModelMultipleChoiceFilter
的查询集参数支持可调用行为。如果传递了一个可调用对象,它将以 request
作为唯一参数被调用。
import django_filters as filters
from django.utils.translation import gettext as _
def ourBranches(request):
if request is None:
return Branch.objects.none()
company = request.user.profile.company
return Branch.objects.filter(company=company)
class UnitFilter(filters.FilterSet):
branch = filters.ModelChoiceFilter(
queryset=ourBranches, empty_label=_("All Branches"))
class Meta:
model = Unit
fields = ('branch', )
并且在视图中,我确保也通过了 request
qs = Unit.objects.all()
filter = UnitFilter(self.request.GET, request=self.request, queryset=qs)
table = UnitTable(filter.qs)