Opened 16 years ago
Closed 10 months ago
#7430 closed Bug (wontfix)
Recursively iterating through a template's nodes
Reported by: | miracle2k | Owned by: | Anders Hovmöller |
---|---|---|---|
Component: | Template system | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Right now, for node in Template() will only yield the top-level nodes. Is this the way it is intended to work? I was expecting to get all nodes, recursively.
The Template.__iter__ code looks like this:
def __iter__(self): for node in self.nodelist: for subnode in node: yield subnode
And Node.__iter__ does:
def __iter__(self): yield self
This looks like a precipe to allow nodes to yield their childnodes, without relying on the existence of the nodelist attribute.
However, nodes like BlockNode and ExtendsNode do not implement __iter__ - only ForNode and IfNode seem to do, and not in the way I would have expected (they don't yield self).
Is this a bug, or per design?
Change History (12)
comment:1 Changed 16 years ago by
comment:2 Changed 16 years ago by
comment:3 Changed 16 years ago by
I don't recall whether this was by design. Does any Django code actually *use* this iter behavior?
comment:4 Changed 16 years ago by
Any of Django's code itself? I quick grep didn't reveal anything obvious. Rendering works via recursive render() calls, so that part doesn't need it.
comment:5 Changed 15 years ago by
Needs tests: | set |
---|---|
Triage Stage: | Unreviewed → Design decision needed |
comment:6 Changed 13 years ago by
Severity: | → Normal |
---|---|
Type: | → Bug |
comment:7 Changed 12 years ago by
Easy pickings: | unset |
---|---|
Resolution: | → needsinfo |
Status: | new → closed |
UI/UX: | unset |
Code changes require more practical justification than this. Feel free to reopen with demonstration of a specific use case, the code that is currently required to achieve it, and the code that would be possible with a change to Django.
comment:8 Changed 10 months ago by
Needs tests: | unset |
---|---|
Resolution: | needsinfo |
Status: | closed → new |
Triage Stage: | Design decision needed → Ready for checkin |
As per a much later report via a PR, Template.__iter__()
looks broken:
>>> from django.template import Template >>> t = Template('Hello, world!') >>> next(iter(t)) ... TypeError: 'TextNode' object is not iterable
I don't recall whether this was by design. Does any Django code actually *use* this iter behavior?
According to the test suite, it doesn't.
I think this can just be removed (as per the PR).
comment:9 Changed 10 months ago by
Owner: | changed from nobody to Anders Hovmöller |
---|---|
Status: | new → assigned |
As per Tim's comment, should be wontfix once merged.
comment:10 Changed 10 months ago by
Just FYI I have working code for walking the syntax tree: https://github.com/boxed/okrand/blob/main/okrand/__init__.py#L262
It's... not ideal as it requires two monkey patches that I've found so far. But I personally don't think having __iter__
on stuff is very useful. There are multiple child nodelists, so iter would be a little weird honestly.
comment:12 Changed 10 months ago by
Resolution: | → wontfix |
---|---|
Status: | assigned → closed |
Triage Stage: | Ready for checkin → Unreviewed |
As per Tim's suggestion on the PR, resolving this as wontfix
, since directly iterating a template's nodes isn't supported.
(Short of a rationale and proof-of-concept, it doesn't seem likely to be added.)
I'm noticing that both ForNode and IfNode do not provide the nodelist attribute. Is the idea that you should use Node.nodelist if it exists, and fall back to the iterator otherwise? Wouldn't it make sense then to have the Node class implement a generic iterator that will yield the items in self.nodelist?