diff --git a/web/core/views.py b/web/core/views.py index b5cf283..3f1ff7a 100644 --- a/web/core/views.py +++ b/web/core/views.py @@ -9,7 +9,7 @@ import csv from .models import Entry from .forms import ImportForm, EntryForm -from .utils import import_csv_bytes, terms, has_wildcards, wildcard_to_regex +from .utils import terms, has_wildcards, wildcard_to_regex, import_csv_bytes # Order + labels used in the Search UI FIELD_ORDER = [ @@ -73,7 +73,7 @@ def search_page(request): Search-first landing. Defaults to Subject, Illustration, Application. Supports: - quoted phrases - - * and ? wildcards (translated to regex when present) + - * and ? wildcards (regex); if regex returns zero, falls back to icontains - AND across tokens, OR across the selected fields """ default_fields = { @@ -104,21 +104,40 @@ def search_page(request): tokens = terms(q) # supports quoted phrases fields = [f for f, sel in selected.items() if sel] or ["subject"] + # ---------- Pass A: regex for wildcard tokens ---------- qs = Entry.objects.all() - - # Build filters: AND across tokens, each token ORs across fields + used_regex = False for tok in tokens: - token_clause = Q() + clause = Q() if has_wildcards(tok): - pattern = wildcard_to_regex(tok) + used_regex = True + pattern = wildcard_to_regex(tok) # e.g. "*love*" -> ".*love.*" for f in fields: - token_clause |= Q(**{f + "__iregex": pattern}) + clause |= Q(**{f + "__iregex": pattern}) else: for f in fields: - token_clause |= Q(**{f + "__icontains": tok}) - qs = qs.filter(token_clause) + clause |= Q(**{f + "__icontains": tok}) + qs = qs.filter(clause) ids = list(qs.order_by("-date_added", "-id").values_list("id", flat=True)) + + # ---------- Pass B (fallback): plain icontains if regex yielded 0 ---------- + if used_regex and not ids: + qs = Entry.objects.all() + for tok in tokens: + clause = Q() + tok_stripped = tok.replace("*", "").replace("?", "") # fallback normalize + for f in fields: + clause |= Q(**{f + "__icontains": tok_stripped}) + qs = qs.filter(clause) + ids = list(qs.order_by("-date_added", "-id").values_list("id", flat=True)) + + # Debug to container logs + try: + print(f"[search] q={q!r} tokens={tokens} fields={fields} count={len(ids)}") + except Exception: + pass + request.session["result_ids"] = ids count = len(ids)