Фильтрация с несколькими полями в django orm - PullRequest
0 голосов
/ 02 февраля 2019

У меня есть несколько полей, которые я могу использовать для фильтрации списка.Я могу использовать все эти поля или некоторые из них в запросе фильтра.Мой взгляд как ниже.Но я не могу получить правильный ответ.Это означает, что некоторые записи, которые, я ожидаю, были выбраны, не выбраны.

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 голосов
/ 02 февраля 2019

Вы делаете это неправильно.Во-первых, позвольте мне посоветовать, что такую ​​фильтрацию следует выполнять методом filter_queryset, а не методом get_queryset или лучше, используйте DjangoFilterBackend из 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, так как это означает методдля фильтрации.

...