Opened 10 years ago
Closed 8 years ago
#26184 closed New feature (fixed)
Allow using custom lookups and transforms in ModelAdmin.search_fields
| Reported by: | Bertrand Bordage | Owned by: | Krzysztof Nazarewski |
|---|---|---|---|
| Component: | contrib.admin | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | berker.peksag@…, camilo.nova@… | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
When you define a ModelAdmin like this:
class MyAdmin(ModelAdmin): search_fields = ['my_field__unaccent']
a FieldDoesNotExist is raised when you try to search something.
This is because the admin fails to identify __unaccent as a valid lookup because django.contrib.admin.utils.lookup_needs_distinct relies on two kludges:
- it assumes that the last part of the lookup expression is always a lookup (
iexact,icontains,search, etc), and that all other parts are fields. In the unaccent scenario, the penultimate part is a transform since the admin generates this expression:myfield__unaccent__icontains - it only checks that lookups are in
django.db.models.sql.constants.QUERY_TERMS. ButQUERY_TERMSis no longer used and should be removed, it only contains "classic" lookups
The solution is to use the new registration API instead, with the get_lookup and get_transform methods.
A better solution would be to make search_fields more consistent with the rest of Django by removing the ^, =, & @ shortcuts. If not, providing them on the whole ORM would be consistent. In my opinion, they should be removed, they complicate Django while limiting its possibilities (what if someone wants exact instead of iexact?). If someone has a lot of fields with the same transforms/lookups, this can be done:
class BookAdmin(ModelAdmin): search_fields = ('title', 'subtitle', 'author_first_name', 'author_last_name', 'publisher') search_fields = [le + '__unaccent__icontains' for le in search_fields]
or even this if you need it often:
class SearchMixin: def get_search_fields(self, request): return [le + '__unaccent__icontains' for le in self.search_fields] class BookAdmin(SearchMixin, ModelAdmin): search_fields = ('title', 'subtitle', 'author_first_name', 'author_last_name', 'publisher')
I’m working on an implementation for one of my projects, I’ll submit it when done.
Change History (10)
comment:1 by , 10 years ago
comment:2 by , 10 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:4 by , 9 years ago
| Cc: | added |
|---|
follow-up: 6 comment:5 by , 8 years ago
| Cc: | added |
|---|
@Bertrand Bordage Did you work on that implementation?
comment:6 by , 8 years ago
@Camilo Nova: No, I almost never use Django admin now, I switched to Wagtail.
comment:7 by , 8 years ago
| Has patch: | set |
|---|---|
| Owner: | changed from to |
| Status: | new → assigned |
comment:8 by , 8 years ago
| Patch needs improvement: | set |
|---|---|
| Summary: | Unable to use custom lookups or transforms in admin `search_fields` → Allow using custom lookups and transforms in ModelAdmin.search_fields |
| Type: | Bug → New feature |
Here’s a workaround that could work as a solution: dezede/dezede@5e8be29.
I kept
get_search_resultsas is to leave the^,=, &@functionalities unchanged, but it should of course be changed, as suggested above.