Opened 4 years ago

Closed 4 years ago

Last modified 4 years ago

#26603 closed Bug (fixed)

Can't use lazy objects as template names with cached loader anymore

Reported by: Sylvain Fankhauser Owned by: Simon Charette
Component: Template system Version: 1.9
Severity: Release blocker Keywords:
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

It looks like commit https://github.com/django/django/commit/bd145e7209a0e628cced10384bd6f62d65c0f211 introduced a regression in Django 1.9.6. Before this commit, you could pass a lazy object to the {% extends %} tag and it would work just fine, however with Django 1.9.6 the following exception is raised:

Template error:
In template /home/vagrant/ENV/local/lib/python2.7/site-packages/parler/templates/admin/parler/change_form.html, error at line 1
   sequence item 0: expected string, __proxy__ found   1 :  {% extends default_change_form_template|default:"admin/change_form.html" %} 
   2 : 
   3 : {% block field_sets %}
   4 : {% if language_tabs %}{% include "admin/parler/language_tabs.html" %}{% endif %}
   5 : {{ block.super }}
   6 : {% endblock %}
   7 : 

Traceback:

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  174.                     response = self.process_exception_by_middleware(e, request)

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  172.                     response = response.render()

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/template/response.py" in render
  160.             self.content = self.rendered_content

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/template/response.py" in rendered_content
  137.         content = template.render(context, self._request)

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/template/backends/django.py" in render
  95.             return self.template.render(context)

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/template/base.py" in render
  206.                     return self._render(context)

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/test/utils.py" in instrumented_test_render
  92.     return self.nodelist.render(context)

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/template/base.py" in render
  992.                 bit = node.render_annotated(context)

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/template/base.py" in render_annotated
  959.             return self.render(context)

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/template/loader_tags.py" in render
  151.         compiled_parent = self.get_parent(context)

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/template/loader_tags.py" in get_parent
  148.         return self.find_template(parent, context)

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/template/loader_tags.py" in find_template
  128.             template_name, skip=history,

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/template/engine.py" in find_template
  157.                         name, template_dirs=dirs, skip=skip,

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/template/loaders/cached.py" in get_template
  49.         key = self.cache_key(template_name, template_dirs, skip)

File "/home/vagrant/ENV/local/lib/python2.7/site-packages/django/template/loaders/cached.py" in cache_key
  103.         return '-'.join(filter(bool, [template_name, skip_prefix, dirs_prefix]))

Exception Type: TypeError at /en/admin/aldryn_newsblog/newsblogconfig/1/change/
Exception Value: sequence item 0: expected string, __proxy__ found

You can easily reproduce the problem in a new project by using the following code in the urls.py file:

from django.views.generic import TemplateView
from django.utils.functional import lazy


class TestView(TemplateView):
    template_name = 'home.html'

    def get_context_data(self, **kwargs):
        context = super(TestView, self).get_context_data(**kwargs)
        context['extended_template'] = lazy(lambda: 'base.html')
        return context

urlpatterns = [
    url(r'^$', TestView.as_view()),
]

And create a file templates/home.html (and adapt the template dirs accordingly):

{% extends extended_template %}

The bug is present on master as well.

Change History (8)

comment:1 Changed 4 years ago by Simon Charette

Owner: changed from nobody to Simon Charette
Severity: NormalRelease blocker
Status: newassigned
Triage Stage: UnreviewedAccepted

comment:2 Changed 4 years ago by Simon Charette

Has patch: set

comment:3 Changed 4 years ago by Tim Graham

Triage Stage: AcceptedReady for checkin

comment:4 Changed 4 years ago by Simon Charette <charette.s@…>

Resolution: fixed
Status: assignedclosed

In 207c5b4:

Fixed #26603 -- Forced lazy template names to text when computing cache key.

Refs #26536.

Thanks Sylvain Fankhauser for the very detailed report.

comment:5 Changed 4 years ago by Simon Charette <charette.s@…>

In 6a67dce:

[1.9.x] Fixed #26603 -- Forced lazy template names to text when computing cache key.

Refs #26536.

Thanks Sylvain Fankhauser for the very detailed report.

Backport of 207c5b4acd410dd39bac31457dae26a0d15b8b93 from master

comment:6 Changed 4 years ago by Vytis Banaitis

The last commit breaks tests in 1.9 because lazystr doesn't exist yet.

======================================================================
ERROR: template_tests.test_loaders (unittest.loader.ModuleImportFailure)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib64/python3.4/unittest/case.py", line 58, in testPartExecutor
    yield
  File "/usr/lib64/python3.4/unittest/case.py", line 577, in run
    testMethod()
  File "/usr/lib64/python3.4/unittest/loader.py", line 32, in testFailure
    raise exception
ImportError: Failed to import test module: template_tests.test_loaders
Traceback (most recent call last):
  File "/usr/lib64/python3.4/unittest/loader.py", line 312, in _find_tests
    module = self._get_module_from_name(name)
  File "/usr/lib64/python3.4/unittest/loader.py", line 290, in _get_module_from_name
    __import__(name)
  File "/home/vytis/src/django/tests/template_tests/test_loaders.py", line 16, in <module>
    from django.utils.functional import lazystr
ImportError: cannot import name 'lazystr'

comment:7 Changed 4 years ago by Simon Charette

I'll take care of that.

comment:8 Changed 4 years ago by Simon Charette <charette.s@…>

In de22123d:

[1.9.x] Refs #26603 -- Defined lazystr for a template loader test.

Thanks vytisb for the report.

Note: See TracTickets for help on using tickets.
Back to Top