Repository navigation
CachedLoader breaks application #73
Description
Activity
Oh, and i should mention that we are using version from master (0.7.0dev1), because earlier version do not work with our project (django 1.9).
Hm, this sounds strange as the
CachedLoaderis usingget_flavourto determine the cache key. Do you have a custom flavour detection middleware in place? Are you loading the templates outside of a request/response cycle?Maybe try hooking some print statements in the
CachedLoaderand see what happens there in your scenario.Hello, and thank you for response.
We do not have custom flavour detection middleware, also we are loading template in request/response cycle.
I will hook prints into cached loader's cache_key function and send message here.
Okay, i did some debugging:
Thats how i modified cached loader:
class CachedLoader(DjangoCachedLoader):
is_usable = Truedef cache_key(self, template_name, template_dirs, *args): if len(args) > 0: # Django >= 1.9 key = super(CachedLoader, self).cache_key(template_name, template_dirs, *args) else: if template_dirs: key = '-'.join([ template_name, hashlib.sha1(force_bytes('|'.join(template_dirs))).hexdigest() ]) else: key = template_name if template_name == 'base.html': # template origins are in args[0] origins = [] for arg in args[0]: origins.append({ 'object': arg, 'object.name': arg.name, 'object.template_name': arg.template_name, 'object.loader_name': arg.loader_name, }) # just output extended debug information pprint.pprint({ 'template_name': template_name, 'template_dirs': template_dirs, 'args[0]': origins, 'cache_key': '{0}:{1}'.format(get_flavour(), key), }) return '{0}:{1}'.format(get_flavour(), key)This code returned this output to me:
{'args[0]': [{'object': <django.template.base.Origin object at 0x7f0dffd9e0b8>, 'object.loader_name': 'django.template.loaders.filesystem.Loader', 'object.name': '/home/user/project/templates/home.html', 'object.template_name': 'home.html'}, {'object': <django.template.base.Origin object at 0x7f0dffdb7da0>, 'object.loader_name': 'django.template.loaders.filesystem.Loader', 'object.name': '/home/user/project/templates/mobile/base.html', 'object.template_name': 'mobile/base.html'}, <few hundreds of same records for an Origin object at 0x7f0dffdb7da0> {'object': <django.template.base.Origin object at 0x7f0dffdb7da0>, 'object.loader_name': 'django.template.loaders.filesystem.Loader', 'object.name': '/home/user/project/templates/mobile/base.html', 'object.template_name': 'mobile/base.html'}], 'cache_key': 'mobile:base.html', 'template_dirs': None, 'template_name': 'base.html'} Fatal Python error: Cannot recover from stack overflow. <stack trace>Our configurations is like this:
templates/home.html → first request goes here
home.html extends base.htmltemplates/base.html → desktop version
templates/mobile/base.html → mobile versionSo it looks like this:
Incoming request starts the homepage view, which tries to render
home.htmltemplate.
Template loader loadshome.htmltemplate and goes tobase.html. As we can see it actually founds themobile/base.htmlinstead of originalbase.html, but then it tries to parsemobile/base.htmland dies by recursion.This is how templates looks:
base.html: just a simple template
home.html:
{% extends "base.html" %}
mobile/base.html:
{% extends "base.html" %} → this recursive extend does not work with CachedLoader.
I should note that Django supports recursive loading of templates (and it is working with non cached loader version).
TEMPLATES configuration variable looks like this:
[{'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': ['/home/user/project/templates'], 'OPTIONS': {'builtins': ['core.templatetags.builtins', 'el_pagination.templatetags.el_pagination_tags'], 'context_processors': ('django.contrib.auth.context_processors.auth', 'django.template.context_processors.request', 'django.template.context_processors.debug', 'django.template.context_processors.i18n', 'django.template.context_processors.media', 'django.template.context_processors.static', 'django.template.context_processors.tz', 'django.contrib.messages.context_processors.messages', 'django_mobile.context_processors.flavour', 'articles.context_processors.from_yandex', 'dom.context_processors.admin_index_modules'), 'libraries': {}, 'loaders': [('django_mobile.loader.CachedLoader', ['django_mobile.loader.Loader', 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader'])]}}]I will be happy if it will be fixed, or at least some workaround found.
Thanks!
Hello!
We are using django-mobile in our project.
We use Django 1.9 and experienced trouble with cached loader: it ruined the application down with exceptions:
./manage.py runserverjust crashed when tried to set flavour to mobileuwsgihas a maximum recursion depth exceeded when tried to set flavour to mobileOur templates configuration is like this:
templates/base.html
templates/mobile/base.html
mobile/base.html has {% extends "base.html" %}
In this situation problem started to appear.
We had to turn off cached loaders at all, because django-mobile's loader is broken and Django's cached loader do not working with django-mobile.
As far as i see, the problem is in django-mobile's CachedLoader implementation — it does not understand what current flavour is, so it generate broken cache key for both base.html and mobile/base.html, which looks like this:
full:base.html
So the mobile template tries to extend "base.html", but gets itself content (with extend) instead of original, root base.html.