All three worker batch-report views (HTML / CSV / PDF) passed raw
query-string values into queryset filters — ?team=abc raised ValueError
deep in the ORM, and the PDF view's display-name lookups raised
Project/Team.DoesNotExist on a deleted id (stale bookmark) → 500s.
New _int_param_or_none() sanitizer coerces filter params at the view
boundary (junk degrades to 'no filter'); the PDF's display-name lookups
fall back to 'All Projects'/'All Teams' on DoesNotExist. Template
dropdowns already compare via |stringformat so int params are safe.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>