mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-24 00:04:16 +03:00
Clean-up refactoring of SearchFilter implementation
This commit is contained in:
parent
aa4cd7e9d7
commit
b4b2dc18fa
|
@ -50,6 +50,13 @@ def total_seconds(timedelta):
|
||||||
return (timedelta.days * 86400.0) + float(timedelta.seconds) + (timedelta.microseconds / 1000000.0)
|
return (timedelta.days * 86400.0) + float(timedelta.seconds) + (timedelta.microseconds / 1000000.0)
|
||||||
|
|
||||||
|
|
||||||
|
def distinct(queryset, base):
|
||||||
|
if settings.DATABASES[queryset.db]["ENGINE"] == "django.db.backends.oracle":
|
||||||
|
# distinct analogue for Oracle users
|
||||||
|
return base.filter(pk__in=set(queryset.values_list('pk', flat=True)))
|
||||||
|
return queryset.distinct()
|
||||||
|
|
||||||
|
|
||||||
# OrderedDict only available in Python 2.7.
|
# OrderedDict only available in Python 2.7.
|
||||||
# This will always be the case in Django 1.7 and above, as these versions
|
# This will always be the case in Django 1.7 and above, as these versions
|
||||||
# no longer support Python 2.6.
|
# no longer support Python 2.6.
|
||||||
|
|
|
@ -7,12 +7,13 @@ from __future__ import unicode_literals
|
||||||
import operator
|
import operator
|
||||||
from functools import reduce
|
from functools import reduce
|
||||||
|
|
||||||
from django.conf import settings
|
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
|
||||||
from rest_framework.compat import django_filters, get_model_name, guardian
|
from rest_framework.compat import (
|
||||||
|
distinct, django_filters, get_model_name, guardian
|
||||||
|
)
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
|
|
||||||
FilterSet = django_filters and django_filters.FilterSet or None
|
FilterSet = django_filters and django_filters.FilterSet or None
|
||||||
|
@ -99,25 +100,27 @@ class SearchFilter(BaseFilterBackend):
|
||||||
def filter_queryset(self, request, queryset, view):
|
def filter_queryset(self, request, queryset, view):
|
||||||
search_fields = getattr(view, 'search_fields', None)
|
search_fields = getattr(view, 'search_fields', None)
|
||||||
|
|
||||||
if not search_fields:
|
orm_lookups = [
|
||||||
|
self.construct_search(six.text_type(search_field))
|
||||||
|
for search_field in search_fields
|
||||||
|
]
|
||||||
|
search_terms = self.get_search_terms(request)
|
||||||
|
|
||||||
|
if not search_fields or not search_terms:
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
original_queryset = queryset
|
base = queryset
|
||||||
orm_lookups = [self.construct_search(six.text_type(search_field))
|
for search_term in search_terms:
|
||||||
for search_field in search_fields]
|
queries = [
|
||||||
|
models.Q(**{orm_lookup: search_term})
|
||||||
|
for orm_lookup in orm_lookups
|
||||||
|
]
|
||||||
|
queryset = queryset.filter(reduce(operator.or_, queries))
|
||||||
|
|
||||||
for search_term in self.get_search_terms(request):
|
# Filtering against a many-to-many field requires us to
|
||||||
or_queries = [models.Q(**{orm_lookup: search_term})
|
# call queryset.distinct() in order to avoid duplicate items
|
||||||
for orm_lookup in orm_lookups]
|
# in the resulting queryset.
|
||||||
queryset = queryset.filter(reduce(operator.or_, or_queries))
|
return distinct(queryset, base)
|
||||||
|
|
||||||
if settings.DATABASES[queryset.db]["ENGINE"] == "django.db.backends.oracle":
|
|
||||||
# distinct analogue for Oracle users
|
|
||||||
queryset = original_queryset.filter(pk__in=set(queryset.values_list('pk', flat=True)))
|
|
||||||
else:
|
|
||||||
queryset = queryset.distinct()
|
|
||||||
|
|
||||||
return queryset
|
|
||||||
|
|
||||||
|
|
||||||
class OrderingFilter(BaseFilterBackend):
|
class OrderingFilter(BaseFilterBackend):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user