mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-07-18 12:12:19 +03:00
Use subquery to remove duplicates in SearchFilter
This commit is contained in:
parent
4f7e9ed3bb
commit
dee83cebf4
|
@ -3,7 +3,6 @@ The `compat` module provides support for backwards compatibility with older
|
||||||
versions of Django/Python, and compatibility wrappers around optional packages.
|
versions of Django/Python, and compatibility wrappers around optional packages.
|
||||||
"""
|
"""
|
||||||
import django
|
import django
|
||||||
from django.conf import settings
|
|
||||||
from django.views.generic import View
|
from django.views.generic import View
|
||||||
|
|
||||||
|
|
||||||
|
@ -14,13 +13,6 @@ def unicode_http_header(value):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
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()
|
|
||||||
|
|
||||||
|
|
||||||
# django.contrib.postgres requires psycopg2
|
# django.contrib.postgres requires psycopg2
|
||||||
try:
|
try:
|
||||||
from django.contrib.postgres import fields as postgres_fields
|
from django.contrib.postgres import fields as postgres_fields
|
||||||
|
|
|
@ -14,7 +14,7 @@ from django.utils.encoding import force_str
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
||||||
from rest_framework import RemovedInDRF317Warning
|
from rest_framework import RemovedInDRF317Warning
|
||||||
from rest_framework.compat import coreapi, coreschema, distinct
|
from rest_framework.compat import coreapi, coreschema
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
|
|
||||||
|
|
||||||
|
@ -127,12 +127,13 @@ class SearchFilter(BaseFilterBackend):
|
||||||
conditions.append(reduce(operator.or_, queries))
|
conditions.append(reduce(operator.or_, queries))
|
||||||
queryset = queryset.filter(reduce(operator.and_, conditions))
|
queryset = queryset.filter(reduce(operator.and_, conditions))
|
||||||
|
|
||||||
|
# Remove duplicates from results, if necessary
|
||||||
if self.must_call_distinct(queryset, search_fields):
|
if self.must_call_distinct(queryset, search_fields):
|
||||||
# Filtering against a many-to-many field requires us to
|
# inspired by django.contrib.admin
|
||||||
# call queryset.distinct() in order to avoid duplicate items
|
# this is more accurate than .distinct form M2M relationship
|
||||||
# in the resulting queryset.
|
# also is cross-database
|
||||||
# We try to avoid this if possible, for performance reasons.
|
queryset = queryset.filter(pk=models.OuterRef('pk'))
|
||||||
queryset = distinct(queryset, base)
|
queryset = base.filter(models.Exists(queryset))
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
def to_html(self, request, queryset, view):
|
def to_html(self, request, queryset, view):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user