Opened 3 hours ago

Last modified 3 hours ago

#37263 assigned Bug

Admin changelist search crashes (500) on `__exact` search_fields with choices and over-matches on BooleanField

Reported by: Adam Johnson Owned by: Adam Johnson
Component: contrib.admin Version: 6.1
Severity: Release blocker Keywords:
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Regression in 4cecf3039586ea738afafb9a28c946bff42c37c1 (#36865), which replaced Cast-based comparison of non-text __exact search fields with per-term validation via the model field's formfield().to_python().
That validation is insufficient for two kinds of fields:

1. Crash (HTTP 500) for fields with choices

For a model field with choices (e.g. IntegerField(choices=...)), formfield() returns a TypedChoiceField whose to_python() returns the raw string unvalidated.
The term then reaches the ORM and IntegerField.get_prep_value() raises ValueError: invalid literal for int() with base 10: 'john'.
Since ModelAdmin.get_search_results() is called outside the IncorrectLookupParameters handling in ChangeList.get_queryset() (django/contrib/admin/views/main.py), the error propagates as a server error.

Minimal repro:

class Client(models.Model):
    name = models.CharField(max_length=30)
    status = models.IntegerField(choices=[(1, "Active"), (2, "Archived")])

class ClientAdmin(admin.ModelAdmin):
    search_fields = ["name", "status__exact"]

Searching for john in the changelist returns HTTP 500 on 6.1 and main; on 6.0 it returned the rows whose name matches.

2. Over-matching for BooleanField

For BooleanField __exact entries, forms.BooleanField.to_python() maps almost any string to True (only "false"/"0" map to False; nothing raises), so any search term OR-matches every row with a True value.

class Account(models.Model):
    name = models.CharField(max_length=30)
    active = models.BooleanField(default=True)

class AccountAdmin(admin.ModelAdmin):
    search_fields = ["name", "active__exact"]

Searching for john returns every active account on 6.1 instead of just john (6.0 behavior).

Change History (1)

comment:1 by Adam Johnson, 3 hours ago

Has patch: set
Note: See TracTickets for help on using tickets.
Back to Top