Opened 9 years ago
Closed 7 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_TERMS
is 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 , 9 years ago
comment:2 by , 9 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:4 by , 8 years ago
Cc: | added |
---|
follow-up: 6 comment:5 by , 7 years ago
Cc: | added |
---|
@Bertrand Bordage Did you work on that implementation?
comment:6 by , 7 years ago
@Camilo Nova: No, I almost never use Django admin now, I switched to Wagtail.
comment:7 by , 7 years ago
Has patch: | set |
---|---|
Owner: | changed from | to
Status: | new → assigned |
comment:8 by , 7 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_results
as is to leave the^
,=
, &@
functionalities unchanged, but it should of course be changed, as suggested above.