在Django ORM多场滤波

时间:2019-02-02 06:04:52

标签: django django-rest-framework

我有一些字段可以用来过滤列表。我可以在过滤器查询中使用所有这些字段或其中一些字段。我的看法如下。但我不能得到正确的答案。这意味着未选中我希望已选择的某些记录。

class UserListAPIView(ListAPIView):

serializer_class = serializers.UserListSerializer
pagination_class = AdminPagination
permission_classes = (IsAuthRolePermission,)

filter_backends = (filters.OrderingFilter,)
ordering_fields = '__all__'


def get_queryset(self):

    full_name     = self.request.query_params.get('full_name', '')
    email         = self.request.query_params.get('email', '')
    facility_name = self.request.query_params.get('facility_name', '')
    user_state    = self.request.query_params.get('user_state', '')

    if full_name or email or facility_name or user_state:

        queryset = User.objects.filter(full_name__icontains=full_name,
                                       email__icontains=email,
                                       facility_name__icontains=facility_name,
                                       user_state__icontains=user_state) \
            .annotate(facility=F('facility_name'),
                      state=F('user_state'),
                      last_access=F('lastAccess')) \
            .order_by('-id').distinct()

    else:
        queryset = User.objects.all()\
            .annotate(facility=F('facility_name'),
                      state=F('user_state'),
                      last_access=F('lastAccess'))\
            .order_by('-id')

    return queryset

1 个答案:

答案 0 :(得分:1)

您做错了方法。首先,让我建议,这种过滤应该在filter_queryset的方法来进行,而不是get_queryset方法或更好,使用DjangoFilterBackend from django-filter这是常见的做法。

现在与您的代码有关,即使未指定过滤器,您也可以添加它们。假设客户端中加入了查询参数full_name=foo,你的代码继续补充email="",facility_name="",user_state="",其很可能不会返回任何东西,因为将没有在数据库中这些值的组合过滤器。所以,更确切地说,不是这样做,指定只添加查询参数。

类似这样的东西:

def get_queryset(self):

    filter_fields = ['full_name', 'email', 'facility_name', 'user_state']

    params = {'{}__icontains'.format(k): v for k,v in self.request.query_params.items() if k in filter_fields}

    queryset = User.objects.filter(**params) \
                .annotate(facility=F('facility_name'),
                          state=F('user_state'),
                          last_access=F('lastAccess')) \
                .order_by('-id').distinct()

    return queryset

再次,应考虑该运动为filter_queryset,因为这是指用于过滤方法。