#23441 closed Bug (fixed)
Maximum recursion depth exceeded when using custom `inclusion_tag` with recursion in templates and `django.template.loaders.cached.Loader`
Reported by: | Venelin Stoykov | Owned by: | nobody |
---|---|---|---|
Component: | Template system | Version: | 1.7 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | yes | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
When custom inclusion_tag
is created which use recursion in the template (call itself) and also template loader used is django.template.loaders.cached.Loader
. In this situation when template containing this inclusion tag is rendered for the second time (then the template is fetched from the cache) then maximum recursion depth exceeded
error is raised.
The reason for this is when {% extends %}
template tag start to look for {% block %}
tags it calls Node.get_nodes_by_type
which start looking for {% block %}
tags in the template. When reach our custom inclusion tag node and call it's get_nodes_by_type
method to look for {% block %}
then start iteration over cached nodes from included template. This will not happen when standard template loaders are used because template for inclusion tag is not parsed yet.
To reproduce the error you can use github repo created for that purpose (https://github.com/vstoykov/wpadmin-test)
I think that there is two possible approaches to fix this, both of which prevent iteration over cached nodes.
- Set
child_nodelists
attribute ofInclusionNode
to be empty iterable (tuple for example). - Change the name of the attribute in which the cached nodes are stored from
nodelist
to something else.
For me the first variant is preferred because we explicitly tell that this node doesn't have any child nodes.
I created a patch with first variant and also a pull request.
Attached Traceback:
Environment: Request Method: GET Request URL: http://localhost:8000/admin/ Django Version: 1.7 Python Version: 2.7.6 Installed Applications: ('wpadmin', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'django.contrib.redirects', 'django.contrib.sites') Installed Middleware: ('django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware') Template error: In template /home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/wpadmin/templates/admin/base_site.html, error at line 1 maximum recursion depth exceeded 1 : {% extends "admin/base.html" %} 2 : {% load i18n wpadmin_tags %} 3 : 4 : {% block title %}{{ title }} | {% wpadmin_render_custom_title %}{% endblock %} 5 : 6 : {% block branding %} 7 : <h1 id="site-name">{% trans 'Django administration' %}</h1> 8 : {% endblock %} 9 : 10 : {% block nav-global %}{% endblock %} 11 : Traceback: File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response 137. response = response.render() File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/response.py" in render 103. self.content = self.rendered_content File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/response.py" in rendered_content 80. content = template.render(context) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in render 148. return self._render(context) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in _render 142. return self.nodelist.render(context) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in render 844. bit = self.render_node(node, context) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/debug.py" in render_node 80. return node.render(context) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/loader_tags.py" in render 126. return compiled_parent._render(context) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in _render 142. return self.nodelist.render(context) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in render 844. bit = self.render_node(node, context) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/debug.py" in render_node 80. return node.render(context) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/loader_tags.py" in render 120. compiled_parent.nodelist.get_nodes_by_type(BlockNode)) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in get_nodes_by_type 854. nodes.extend(node.get_nodes_by_type(nodetype)) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in get_nodes_by_type 831. nodes.extend(nodelist.get_nodes_by_type(nodetype)) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in get_nodes_by_type 854. nodes.extend(node.get_nodes_by_type(nodetype)) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in get_nodes_by_type 831. nodes.extend(nodelist.get_nodes_by_type(nodetype)) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in get_nodes_by_type 854. nodes.extend(node.get_nodes_by_type(nodetype)) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in get_nodes_by_type 831. nodes.extend(nodelist.get_nodes_by_type(nodetype)) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in get_nodes_by_type 854. nodes.extend(node.get_nodes_by_type(nodetype)) ............................ File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in get_nodes_by_type 831. nodes.extend(nodelist.get_nodes_by_type(nodetype)) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in get_nodes_by_type 854. nodes.extend(node.get_nodes_by_type(nodetype)) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/base.py" in get_nodes_by_type 829. nodelist = getattr(self, attr, None) File "/home/venko/.pyvirtualenvs/django-max-recursion/local/lib/python2.7/site-packages/django/template/defaulttags.py" in nodelist 298. return NodeList(node for _, nodelist in self.conditions_nodelists for node in nodelist) Exception Type: RuntimeError at /admin/ Exception Value: maximum recursion depth exceeded
Attachments (1)
Change History (7)
by , 10 years ago
Attachment: | 0001-Prevent-maximumrecursiondepthexceededintemplates.patch added |
---|
comment:1 by , 10 years ago
Description: | modified (diff) |
---|
comment:2 by , 10 years ago
Needs tests: | set |
---|---|
Triage Stage: | Unreviewed → Accepted |
I haven't verified that the issue isn't a bug in the custom include tag, but tests are at least needed before we can commit this.
comment:3 by , 10 years ago
Component: | Uncategorized → Template system |
---|
comment:4 by , 10 years ago
I updated my pull request with very specific test which describes the problem which can lead in some circumstances to the "maximum recursion depth exceeded" error.
Prevent maximum recursion depth exceeded in templates