#28782: Template variable resolution on objects that are no mappings but implement __getitem__ -------------------------------------+------------------------------------- Reporter: Frank | Owner: Frank Sachsenheim Sachsenheim | Type: Bug | Status: assigned Component: Template | Version: master system | Severity: Normal | Keywords: Triage Stage: | Has patch: 0 Unreviewed | Needs documentation: 0 | Needs tests: 0 Patch needs improvement: 0 | Easy pickings: 0 UI/UX: 0 | -------------------------------------+------------------------------------- there are classes in the Pythoniverse that implement a `__getitem__` method for the sake of syntactical sweetness, but they are no mappings. (in my case it's a wrapper around an xml document where `__getitem__` returns the result of xpath evaluations. there are other use-cases around, but i don't remember any atm.). this causes a lookup in a template rendering context on an attribute of such instances to return an unexpected value, because `foo[bar]` doesn't necessarily raise an exception and returns some value, while `foo.bar` was intended. this is caused by the very implicit implementation of `django.template.base.Variable._resolve_lookup`.
my approach to solve this issue is to refactor that method to an explicit behaviour mainly based on type checks, so a member lookup is only performed on instances that base on `collections.abc.Mapping` which any implementation of a mapping should. my rationale is that the documentations mentions a dictionary (though [https://docs.python.org/3/glossary.html#term-mapping mapping] would be more precise term) lookup, not a lookup via `__getitem__`, and dictionary/mapping objects should base on the mentioned abstract class (the why is elaborated in [https://www.python.org/dev/peps/pep-3119/#rationale PEP 3119]). beside solving my problem, i would argue that in doubt "explicit is better than implicit" excels "it's better to ask forgiveness than to ask permission" and the explicit approach is more comprehensible. atm i got this working for all tests in `template_tests`, but still need to figure out why some more complex tests fail. so, i could need some feedback at this point before i continue. one question is whether access to non-mappings via `__getitem__` should be supported as last resort with a deprecation warning. two related issues came up while working on it: 1) i didn't research why this was implemented, but the possiblity to lookup attributes on context objects is rather ambigious imo. could this design decision be reverted? (sidenote: using `SimpleNamespace` objects as context seems reasonable though, and they can easily be converted to a mapping with `vars`.) 2) it seems to me that `django.template.context.Basecontext` could be based on `collections.ChainMap` and it may then even allow to simplify the `…._resolve_lookup` implementation. shall i give it a shot while i'm at it? -- Ticket URL: <https://code.djangoproject.com/ticket/28782> Django <https://code.djangoproject.com/> The Web framework for perfectionists with deadlines. -- You received this message because you are subscribed to the Google Groups "Django updates" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-updates+unsubscr...@googlegroups.com. To post to this group, send email to django-updates@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/django-updates/054.bccdbcba2069b6cf0064341e2e508030%40djangoproject.com. For more options, visit https://groups.google.com/d/optout.