Skip to content

Commit f8825ba

Browse files
committed
Add unaccent to SearchFilter
1 parent 9864c47 commit f8825ba

File tree

3 files changed

+28
-2
lines changed

3 files changed

+28
-2
lines changed

docs/api-guide/filtering.md

+2
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,7 @@ The search behavior may be specified by prefixing field names in `search_fields`
230230
| `$` | `iregex` | Regex search. |
231231
| `@` | `search` | Full-text search (Currently only supported Django's [PostgreSQL backend][postgres-search]). |
232232
| None | `icontains` | Contains search (Default). |
233+
| `&` | `unaccent` | Accent-insensitive search. (Currently only supported Django's [PostgreSQL backend][postgres-lookups]). |
233234

234235
For example:
235236

@@ -370,3 +371,4 @@ The [djangorestframework-word-filter][django-rest-framework-word-search-filter]
370371
[HStoreField]: https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/fields/#hstorefield
371372
[JSONField]: https://docs.djangoproject.com/en/3.0/ref/contrib/postgres/fields/#jsonfield
372373
[postgres-search]: https://docs.djangoproject.com/en/stable/ref/contrib/postgres/search/
374+
[postgres-lookups]: https://docs.djangoproject.com/en/stable/ref/contrib/postgres/lookups/#unaccent

rest_framework/filters.py

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ class SearchFilter(BaseFilterBackend):
6868
'=': 'iexact',
6969
'@': 'search',
7070
'$': 'iregex',
71+
'&': 'unaccent',
7172
}
7273
search_title = _('Search')
7374
search_description = _('A search term.')

tests/test_filters.py

+25-2
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33

44
import pytest
55
from django.core.exceptions import ImproperlyConfigured
6-
from django.db import models
6+
from django.db import connections, models
77
from django.db.models import CharField, Transform
88
from django.db.models.functions import Concat, Upper
99
from django.test import SimpleTestCase, TestCase
1010
from django.test.utils import override_settings
1111

1212
from rest_framework import filters, generics, serializers
13-
from rest_framework.compat import coreschema
13+
from rest_framework.compat import coreschema, postgres_fields
1414
from rest_framework.exceptions import ValidationError
1515
from rest_framework.test import APIRequestFactory
1616

@@ -146,6 +146,29 @@ class SearchListView(generics.ListAPIView):
146146
{'id': 2, 'title': 'zz', 'text': 'bcd'}
147147
]
148148

149+
150+
@pytest.mark.skipif(not postgres_fields, reason='psycopg2 is not installed')
151+
class SearchPostgreSQLFilterTests(TestCase):
152+
def setUp(self):
153+
connections.databases['default']['ENGINE'] = 'django.db.backends.postgresql'
154+
connections.databases['default']['NAME'] = ':memory:'
155+
156+
def test_unaccent_search(self):
157+
class SearchListView(generics.ListAPIView):
158+
queryset = SearchFilterModel.objects.all()
159+
serializer_class = SearchFilterSerializer
160+
filter_backends = (filters.SearchFilter,)
161+
search_fields = ('title', '&text')
162+
163+
obj = SearchFilterModel(title='Accent títle', text='Accent téxt').save()
164+
view = SearchListView.as_view()
165+
lower_and_unaccent_text = 'accent text'
166+
request = factory.get('/', {'search': lower_and_unaccent_text})
167+
response = view(request)
168+
assert response.data == [
169+
{'id': obj.id, 'title': 'Accent títle', 'text': 'Accent téxt'}
170+
]
171+
149172
def test_regexp_search(self):
150173
class SearchListView(generics.ListAPIView):
151174
queryset = SearchFilterModel.objects.all()

0 commit comments

Comments
 (0)