根据请求自定义django-filter ModelChoiceFilter(select)和ModelMultipleChoiceFilter(多选)菜单中的查询集

时间:2018-05-07 03:46:21

标签: django django-rest-framework django-filter

我在两个地方使用django-filter:我的Django Rest Framework API,以及我的FilterViews(Django过滤器的通用列表视图)。在我的情况下FilterViews我显示了要过滤的选择框(ModelChoiceFilter)和多选框(ModelMultipleChoiceFilter)。

我需要能够根据请求中的字段限制那些选择和多选输入中的内容。

更改在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 ViewSet:

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

在显示视图时,我无法在Dataset中找到编辑filter_class字段的任何位置。

这在Django FormView通用视图中非常简单,但FieldViewSet与通用视图遵循相同的get_form()结构并不显示。它在管理员中也相对简单,但DRF / Django-Filter似乎也不遵循这种结构。

有没有办法在每个请求的基础上自定义这些输入中的查询集?最好是在FilterViews和HTML API浏览器中,但只有在FilterViews中,如果HTML API浏览器过于复杂,那就没问题。

2 个答案:

答案 0 :(得分:2)

我也很难找到解决方法。

我通过以下方法解决了(我认为):

views.py

<!doctype html>
<html>

<head>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.2.0/vuetify.min.css" />
</head>

<body>
  <div id="app"></div>
  <script src="https://cdn.jsdelivr.net/npm/vue@2.5.17/dist/vue.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/vuetify/1.2.0/vuetify.min.js"></script>
</body>

</html>

filters.py

table_filter = ExampleFilter(request.GET, kwarg_I_want_to_pass=request.user, queryset=qs)

答案 1 :(得分:1)

经过数小时的搜索,我在官方文档here中找到了解决方案!

ModelChoiceFilterModelMultipleChoiceFilter的queryset参数支持可调用行为。如果传递了Callable,它将以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)