Explanation¶
Loose coupling to the core package¶
django-admin-search-query depends on django-search-query through an
ordinary version floor in its pyproject.toml
(django-search-query>=0.1.0a0), the same way any other consumer of the
query language would. There is no private coupling underneath that pin: the
mixin only ever calls the same public surface documented in
API reference –
search_query_to_q(),
QueryParseError, and the highlighter that
backs Colored search input. Nothing in the core package imports or knows
about the admin integration at all; the dependency arrow points one way.
That looseness is deliberate. django-search-query stays usable in any
Django project – a REST endpoint, a management command, a plain view –
whether or not the admin is even installed. The admin integration is the
optional layer built on top, not a requirement the core package carries for
everyone.
No-JavaScript degradation¶
The colored input is a progressive enhancement of an admin feature that
already works: the stock <input id=searchbar> and Django’s own
search_fields matching.
SearchQueryAdminMixin renders the
search box through a per-admin change_list.html that calls
{{ block.super }} to render Django’s own search form untouched – facets,
hidden filter parameters, and help text stay whatever the installed Django
version renders – and only adds one thing after it: a hidden data-* config
element carrying the URLs of the search-tokens/ and search-highlight/
endpoints (see API reference), emitted only when search_query_registry
is set.
search-input.js reads that config element on load, finds the stock
#searchbar input next to it, and enhances it into the colored editor
described in Colored search input. If JavaScript never runs – disabled,
blocked, or the request never reaches the browser at all – the config
element is inert markup and #searchbar is still the plain Django input:
typing and submitting the form sends ?q= exactly as it always did, and
the mixin still compiles it server-side. The search box never depends on
JavaScript to function; JavaScript only makes it nicer to type into.
The same fallback also covers a query that is JavaScript-typed but does
not parse. A half-finished quote, an unknown field, a stray operator –
anything that raises QueryParseError (or
an empty term, or an admin with no search_query_registry configured) makes
get_search_results()
fall back to super().get_search_results(...), Django’s own
search_fields behavior. No-JS submissions and unparseable JS submissions
land on the same code path, so the admin search box is never worse than
stock ModelAdmin – only ever better, when the query happens to parse.