#36865 closed Bug (fixed)
Casting on __exact searches over non-text fields in admin misses indexes
| Reported by: | Mike Lissner | Owned by: | Mike Lissner |
|---|---|---|---|
| Component: | contrib.admin | Version: | 5.2 |
| Severity: | Normal | Keywords: | search_fields cast |
| Cc: | Triage Stage: | Ready for checkin | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
https://code.djangoproject.com/ticket/26001 from 10 years ago was fixed in PR https://github.com/django/django/pull/17885/, which was released in Django 5.2.
Unfortunately, this fix casts all admin search queries to varchar, which makes the query miss the DB index instead of using it. In large tables, this results in the query timing out, as documented as a comment on the original issue:
https://code.djangoproject.com/ticket/26001#comment:24
And in my project's issue tracker:
https://github.com/freelawproject/courtlistener/issues/6790
We're fixing this in our system by patching the get_search_results method:
https://github.com/freelawproject/courtlistener/pull/6792
I'm not at all familiar with this part of Django, but I spent some time with claude and I think I have a fix here:
https://github.com/django/django/pull/20538
I did my best to be surgical and to add tests, but, again, this is foreign stuff to me. I hope this helps.
Change History (15)
comment:1 by , 3 weeks ago
| Keywords: | search_fields cast added; search regression removed |
|---|---|
| Needs tests: | set |
| Patch needs improvement: | set |
| Triage Stage: | Unreviewed → Accepted |
follow-up: 4 comment:2 by , 3 weeks ago
Thanks. I've updated the title of the PR so it links here (magic?) and I've pushed a commit with the change you suggest here. I agree — much better. Again, I've had a lot of help from Claude on this, so hopefully the code is good. It's a change I wouldn't have dared a few months ago, but I'm hopeful will be good enough now.
I see this ticket says it needs tests and that it needs improvement. I'm assuming it's up to maintainers to uncheck those, yes?
comment:3 by , 3 weeks ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:4 by , 3 weeks ago
Replying to Mike Lissner:
I see this ticket says it needs tests and that it needs improvement. I'm assuming it's up to maintainers to uncheck those, yes?
Thank you Mike!
Once you've completed your work, you can switch "needs tests" and "patch needs improvement" to no.
When "needs tests", "needs patch improvement", and "needs documentation" are all set to no, it will be added to the review queue and can proceed after being reviewed by maintainers or reviewers.
I think this document might be helpful :)
comment:5 by , 3 weeks ago
| Needs tests: | unset |
|---|---|
| Patch needs improvement: | unset |
comment:7 by , 8 days ago
| Patch needs improvement: | set |
|---|
comment:8 by , 7 days ago
| Patch needs improvement: | unset |
|---|
Tweaks made, pushed. Ready for more review, bosses.
comment:9 by , 7 days ago
| Needs tests: | set |
|---|---|
| Patch needs improvement: | set |
comment:10 by , 7 days ago
| Patch needs improvement: | unset |
|---|
comment:11 by , 7 days ago
| Needs tests: | unset |
|---|
comment:12 by , 7 days ago
| Summary: | Query casting introduced in Django 5.2 makes queries miss DB indexes → Casting on __exact searches over non-text fields in admin misses indexes |
|---|---|
| Triage Stage: | Accepted → Ready for checkin |
| Version: | 6.0 → 5.2 |
This problem was discussed in a follow up MR to #26001.
As pointed out on the proposed patch (which you should prefix with #36865 to be automatically linked here Mike) using either
field.to_python(orfield.formfield().to_pythonas we're dealing with untrusted user input) can likely be used as a signal to determine if acastis necessary.I'm also wondering why we even search against cast'ed to text integer field when provided a string not composed of digits (AKA when it fails
to_python) when using theexactlookup. It seems like the logic could be adjusted the other way around by avoiding exact lookups for search terms that search fields failto_pythonand we could drop the casting altogether.e.g.
then a search of the form
?q=foo 2010-01-15should result inWhere we don't even try
dob_str="foo"asDateField.formfield().to_python("foo")identity that the value is not valid for this field and thus cannot be an exact match.