multiseek core:
MultiseekRegistry.get_query_recursiveno longer flags a clause withimpacts_query() == False(e.g.CONTAINSwith an empty value) as anUnknownOperationerror. It's now a silent no-op, matching what the semantics always claimed. Previously users saw an "Errors occurred" banner the moment they clicked Send Query on the default empty field.UnknownOperationraised inparse_fieldnow includes the list of valid operators for the offending field, instead of just naming the invalid one.- Parse failures inside
get_query_recursiveare logged at WARNING withexc_info=Trueso the server log shows traceback / context instead of a bareUnknownOperation().
Example projects (under examples/, not shipped on PyPI):
- Four runnable reference frontends — Foundation 6 + jQuery (vendored),
Bootstrap 5 + jQuery, Bootstrap 5 + Alpine.js, and pure htmx — plus a
run_example.shsetup/run/test helper at the repo root. - Each ships a
manage.py fetch_assetscommand that downloads its JS/CSS dependencies intostatic/multiseek/vendor/so the demos don't depend on public CDNs at runtime (and CI doesn't fail when an egress is blocked). - Playwright smoke tests for every variant.
Security & correctness:
- CSRF protection enforced on
/results/and/save_form/. Previously every multiseek URL was wrapped incsrf_exempt. Downstream projects with custom templates must include{% csrf_token %}and surface the token to their JS layer. The bundled templates handle this automatically. - Concurrency race fixed on the cached
MultiseekRegistry: parse errors no longer live on shared instance state.get_query()andget_query_for_model()accept an optionalerrors=list parameter. Backwards compatible for callers that ignore it. - XSS escape in
describe_multiseek_data(): user-suppliedprev_opandoperatorare HTML-escaped before being inlined into the description rendered with|safe.StringQueryObject.value_for_descriptionnow returns aSafeString. - URL routing:
load_form/<pk>no longer accepts trailing path segments. Allurl()/re_pathpatterns migrated topath()with<int:>converters where applicable. - Manual-exclusion list-full returns HTTP 400 (Bad Request) instead of 403 (Forbidden).
Modernization:
- Drop Python 2 / six-era cruft (
from builtins import str as textandtext(...)wrappers,class X(object):,super(Cls, self)…,u"..."prefixes,# -*- encoding: utf-8 -*-headers). - Drop the
mockthird-party dependency in favour of stdlibunittest.mock. - Drop the dead
django.db.models.options.get_verbose_nameimport shim (the fallback path has been the only live one since Django 1.9). - Drop the dead
if django.VERSION > (1, 8):template-context-processors branch in the demo project, plus theTEMPLATE_DEBUG,sys.argvmiddleware-stripping hack, andAmerica/ChicagoTIME_ZONE.
Tooling:
- Add
ruffto dev deps; enableruff checkandruff format --checkas hard gates in CI (no more|| true). - Format the codebase with
ruff format. - Drop unused
coverallsdev dep.
Public API:
- Re-export the public API from
multiseekso you canfrom multiseek import create_registry, StringQueryObject, …directly. - Add type hints to
QueryObject,MultiseekRegistry,create_registry,get_registry, and the major subclass constructors.
Tests:
- Add regression tests for each of the substantive fixes above (race, CSRF, XSS, URL routing, list-full status code, public-API re-exports).
- Bump version after CI matrix touch-ups.
- Add safety margin for test_frame_bug teardown race condition.
- Add Django 6.0 to supported configurations (Python 3.12+ only).
- use GitHub Actions instead of Travis-CI
- Django 3.2 support,
- extract ordering and default queryset generation from
get_query_for_model, creatingget_default_queryset_for_modelandapply_ordering_to_queryset.
- better date field handling when using with operators like greater, lesser, greater or equal, lesser or equal
- create a placeholder and an exception for form "parse errors"
- fix parameter passing in
describe_multiseek_data
- fix for DateQueryObject when there was range given
- fix for
impacts_queryparameters passing & test
- Foundation 6 as the only supported theme