Skip to content
Open
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/api-guide/filtering.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ The search behavior may be specified by prefixing field names in `search_fields`
| `$` | `iregex` | Regex search. |
| `@` | `search` | Full-text search (Currently only supported Django's [PostgreSQL backend][postgres-search]). |
| None | `icontains` | Contains search (Default). |
| `&` | `unaccent` | Accent-insensitive search. (Currently only supported Django's [PostgreSQL backend][postgres-lookups]). |

For example:

Expand Down Expand Up @@ -370,3 +371,4 @@ The [djangorestframework-word-filter][django-rest-framework-word-search-filter]
[HStoreField]: https://docs.djangoproject.com/en/stable/ref/contrib/postgres/fields/#hstorefield
[JSONField]: https://docs.djangoproject.com/en/stable/ref/models/fields/#django.db.models.JSONField
[postgres-search]: https://docs.djangoproject.com/en/stable/ref/contrib/postgres/search/
[postgres-lookups]: https://docs.djangoproject.com/en/stable/ref/contrib/postgres/lookups/#unaccent
1 change: 1 addition & 0 deletions rest_framework/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ class SearchFilter(BaseFilterBackend):
'=': 'iexact',
'@': 'search',
'$': 'iregex',
'&': 'unaccent',
}
search_title = _('Search')
search_description = _('A search term.')
Expand Down
20 changes: 20 additions & 0 deletions tests/test_filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,26 @@ def as_sql(self, compiler, connection):
{'id': 2, 'title': 'zz', 'text': 'bcd'},
]

@pytest.mark.requires_postgres
def test_search_field_with_unaccent(self):
SearchFilterModel.objects.create(title='Jeremy', text='jeremy')
SearchFilterModel.objects.create(title='Jérémy', text='jérémy')
SearchFilterModel.objects.create(title='Jérémie', text='jérémie')
SearchFilterModel.objects.create(title='Jeremie', text='jeremie')

class SearchListView(generics.ListAPIView):
queryset = SearchFilterModel.objects.all()
serializer_class = SearchFilterSerializer
filter_backends = (filters.SearchFilter,)
search_fields = ('&title',)

view = SearchListView.as_view()

request = factory.get('/', {'search': 'Jerem'})
response = view(request)
assert len(response.data) == 4
assert {item['title'] for item in response.data} == {'Jeremy', 'Jérémy', 'Jérémie', 'Jeremie'}

def test_search_field_with_multiple_words(self):
class SearchListView(generics.ListAPIView):
queryset = SearchFilterModel.objects.all()
Expand Down
Loading