Opened 2 hours ago
Last modified 82 minutes ago
#37318 assigned Bug
first, last, and random template filters raise KeyError on a dict instead of failing gracefully — at Initial Version
| Reported by: | Akshat Kansal | Owned by: | Akshat Kansal |
|---|---|---|---|
| Component: | Template system | Version: | dev |
| Severity: | Normal | Keywords: | defaultfilters first last random |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
The first, last and random template filters raise KeyError when given a
dictionary, instead of failing gracefully the way they do for an empty list.
How to reproduce
import django from django.conf import settings settings.configure(TEMPLATES=[{ "BACKEND": "django.template.backends.django.DjangoTemplates", "DIRS": [], "APP_DIRS": False, "OPTIONS": {}, }]) django.setup() from django.template import Template, Context Template("{{ d|first }}").render(Context({"d": []})) # returns '' Template("{{ d|first }}").render(Context({"d": {"a": 1}})) # KeyError: 0 Template("{{ d|last }}").render(Context({"d": {}})) # KeyError: -1
A list degrades to an empty string. A dict raises KeyError, which escapes
template rendering and becomes a 500. Dicts are common in template contexts,
so this is reachable from an ordinary template.
Why this looks like a bug
first() already catches IndexError so that a wrong-shaped value degrades
instead of raising:
def first(value): try: return value[0] except IndexError: return ""
A dict is the same class of mistake as an empty list, but one returns "" and
the other 500s. The inconsistency is the complaint, not the fact that dicts
are unsupported.
I am happy to write the patch and tests if this is accepted.
Reproduced on main @ 5180f82 (6.2.dev).
Run the reproduction yourself before you submit — that part isn't about policy, it's that you'll be asked follow-up questions and should have seen the failure with your own eyes.