Update web/core/views.py

This commit is contained in:
Joshua Laymon 2025-08-13 05:15:28 +00:00
parent 38755968cd
commit 5aff2bde40

View File

@ -9,7 +9,7 @@ import csv
from .models import Entry from .models import Entry
from .forms import ImportForm, EntryForm 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 # Order + labels used in the Search UI
FIELD_ORDER = [ FIELD_ORDER = [
@ -73,7 +73,7 @@ def search_page(request):
Search-first landing. Defaults to Subject, Illustration, Application. Search-first landing. Defaults to Subject, Illustration, Application.
Supports: Supports:
- quoted phrases - 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 - AND across tokens, OR across the selected fields
""" """
default_fields = { default_fields = {
@ -104,21 +104,40 @@ def search_page(request):
tokens = terms(q) # supports quoted phrases tokens = terms(q) # supports quoted phrases
fields = [f for f, sel in selected.items() if sel] or ["subject"] fields = [f for f, sel in selected.items() if sel] or ["subject"]
# ---------- Pass A: regex for wildcard tokens ----------
qs = Entry.objects.all() qs = Entry.objects.all()
used_regex = False
# Build filters: AND across tokens, each token ORs across fields
for tok in tokens: for tok in tokens:
token_clause = Q() clause = Q()
if has_wildcards(tok): 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: for f in fields:
token_clause |= Q(**{f + "__iregex": pattern}) clause |= Q(**{f + "__iregex": pattern})
else: else:
for f in fields: for f in fields:
token_clause |= Q(**{f + "__icontains": tok}) clause |= Q(**{f + "__icontains": tok})
qs = qs.filter(token_clause) qs = qs.filter(clause)
ids = list(qs.order_by("-date_added", "-id").values_list("id", flat=True)) 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 request.session["result_ids"] = ids
count = len(ids) count = len(ids)