Why would Django (1.5.1) call Loader.load_template_source() 69 times? -


my problem manifested "maximum recursion depth exceeded" error in run-of-the-mill listview. after digging around, found ton of cache hits originating in dbtemplates every attempt made load corresponding page. prompted me write own template loader, @ point became apparent django calling load_template_source sixty-nine times every time page loaded.

why django call load_template_source multiple times?

visitor_index (db template)

<!doctype html> <html lang="en">     <head>         <title>{{ site.name }}</title>     </head>     <body id="home">     <pre>         starting         {% video in videos %}             {{ video.headline }}         {% endfor %}     </pre>     </body> </html> 

urls.py

from django.conf.urls import include, url django.conf.urls.defaults import patterns videos.views import *  urlpatterns = patterns('',     url(r'^$', visitorindex.as_view(), name='index'), ) 

views.py

import logging django.views.generic import listview videos.models import video  logger = logging.getlogger(__name__)  class visitorindex(listview):     context_object_name = 'videos'     template_name = 'visitor_index'      def get_queryset(self):         logger.debug('visitorindex.get_queryset()')         return video.on_site.filter(privacy_mode='pub') 

loader.py

import logging django.template import templatedoesnotexist django.template.loader import baseloader dbtemplates.models import template  logger = logging.getlogger(__name__)  class loader(baseloader):     is_usable = true      def load_template_source(self, template_name, template_dirs=none):         try:             logger.debug('loader.load_template_source(%s, %s)' % (template_name, template_dirs))             template = template.on_site.get(slug__exact=template_name).template_body             logger.debug('loaded template.')             return template, template_name         except template.doesnotexist:             logger.debug('template.doesnotexist caught.')             raise templatedoesnotexist, template_name 

models.py

import logging django.contrib.sites.models import site django.contrib.sites.managers import currentsitemanager django.db import models  logger = logging.getlogger('__name__')  class template(models.model):     slug = models.charfield(max_length=80)     template_body = models.textfield()     site = models.foreignkey(site)      objects = models.manager()     on_site = currentsitemanager('site')      def __unicode__(self):         return self.slug 

settings.py

template_loaders = (     'django.template.loaders.filesystem.loader',     'django.template.loaders.app_directories.loader',     'dbtemplates.loader.loader', ) 

app.log (updated trace)

2013-05-09 19:15:43,634 [debug] dynamicsites.middleware: env_hostnames lookup subdomain=none domain=mydomain.com domain_unsplit=mydomain.com 2013-05-09 19:15:43,634 [debug] dynamicsites.middleware: checking database domain=mydomain.com 2013-05-09 19:15:43,679 [debug] dynamicsites.middleware: using site id=2 domain=mydomain.com 2013-05-09 19:15:43,714 [debug] videos.views: visitorindex.get_queryset() 2013-05-09 19:15:43,716 [debug] django.template.response: simpletemplateresponse.rendered_content() 2013-05-09 19:15:43,717 [debug] django.template.response: start self.resolve_template() 2013-05-09 19:15:43,717 [debug] django.template.response: simpletemplateresponse.resolve_template().  found list or tuple. 2013-05-09 19:15:43,717 [debug] django.template.response: calling loader.select_template(template=['visitor_index', u'videos/video_list.html']) 2013-05-09 19:15:43,720 [debug] dbtemplates.loader: loader.load_template_source(visitor_index, none) 2013-05-09 19:15:43,722 [debug] dbtemplates.loader:   file "/usr/lib/python2.7/threading.py", line 525, in __bootstrap     self.__bootstrap_inner()   file "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner     self.run()   file "/usr/lib/python2.7/threading.py", line 505, in run     self.__target(*self.__args, **self.__kwargs)   file "/usr/lib/python2.7/socketserver.py", line 593, in process_request_thread     self.finish_request(request, client_address)   file "/usr/lib/python2.7/socketserver.py", line 334, in finish_request     self.requesthandlerclass(request, client_address, self)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/core/servers/basehttp.py", line 150, in __init__     super(wsgirequesthandler, self).__init__(*args, **kwargs)   file "/usr/lib/python2.7/socketserver.py", line 649, in __init__     self.handle()   file "/usr/lib/python2.7/wsgiref/simple_server.py", line 124, in handle     handler.run(self.server.get_app())   file "/usr/lib/python2.7/wsgiref/handlers.py", line 85, in run     self.result = application(self.environ, self.start_response)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/contrib/staticfiles/handlers.py", line 72, in __call__     return self.application(environ, start_response)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 255, in __call__     response = self.get_response(request)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 140, in get_response     response = response.render()   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/response.py", line 121, in render     self.content = self.rendered_content   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/response.py", line 91, in rendered_content     template = self.resolve_template(self.template_name)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/response.py", line 60, in resolve_template     t = loader.select_template(template)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/loader.py", line 188, in select_template     return get_template(template_name)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/loader.py", line 146, in get_template     template, origin = find_template(template_name)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/loader.py", line 135, in find_template     source, display_name = loader(name, dirs)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/loader.py", line 43, in __call__     return self.load_template(template_name, template_dirs)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/loader.py", line 46, in load_template     source, display_name = self.load_template_source(template_name, template_dirs)   file "/home/wesley/howl/dbtemplates/loader.py", line 19, in load_template_source     logger.debug(''.join(traceback.format_stack()))  2013-05-09 19:15:43,885 [debug] dbtemplates.loader: loaded template. 2013-05-09 19:15:43,886 [debug] django.template.response: done. 2013-05-09 19:15:43,887 [debug] django.template.response: done.  <django.template.base.template object @ 0x7fbdf8215050> 2013-05-09 19:15:43,887 [debug] django.template.response: start self.resolve_context() 2013-05-09 19:15:43,920 [debug] django.template.response: start template.render(context) 2013-05-09 19:15:43,920 [debug] django.template.base: template.render(context) 2013-05-09 19:15:43,920 [debug] django.template.base:     context.render_context.push() 2013-05-09 19:15:43,920 [debug] django.template.base:     done. 2013-05-09 19:15:43,921 [debug] django.template.base: try self._render(context) 2013-05-09 19:15:43,932 [debug] dbtemplates.loader: loader.load_template_source(visitor_index, none) 2013-05-09 19:15:43,933 [debug] dbtemplates.loader:   file "/usr/lib/python2.7/threading.py", line 525, in __bootstrap     self.__bootstrap_inner()   file "/usr/lib/python2.7/threading.py", line 552, in __bootstrap_inner     self.run()   file "/usr/lib/python2.7/threading.py", line 505, in run     self.__target(*self.__args, **self.__kwargs)   file "/usr/lib/python2.7/socketserver.py", line 593, in process_request_thread     self.finish_request(request, client_address)   file "/usr/lib/python2.7/socketserver.py", line 334, in finish_request     self.requesthandlerclass(request, client_address, self)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/core/servers/basehttp.py", line 150, in __init__     super(wsgirequesthandler, self).__init__(*args, **kwargs)   file "/usr/lib/python2.7/socketserver.py", line 649, in __init__     self.handle()   file "/usr/lib/python2.7/wsgiref/simple_server.py", line 124, in handle     handler.run(self.server.get_app())   file "/usr/lib/python2.7/wsgiref/handlers.py", line 85, in run     self.result = application(self.environ, self.start_response)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/contrib/staticfiles/handlers.py", line 72, in __call__     return self.application(environ, start_response)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/core/handlers/wsgi.py", line 255, in __call__     response = self.get_response(request)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 140, in get_response     response = response.render()   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/response.py", line 121, in render     self.content = self.rendered_content   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/response.py", line 97, in rendered_content     content = template.render(context)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/base.py", line 146, in render     return self._render(context)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/test/utils.py", line 65, in instrumented_test_render     return self.nodelist.render(context)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/base.py", line 837, in render     bit = self.render_node(node, context)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/debug.py", line 74, in render_node     return node.render(context)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/defaulttags.py", line 148, in render     len_values = len(values)   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/db/models/query.py", line 90, in __len__     self._result_cache = list(self.iterator())   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/db/models/query.py", line 301, in iterator     row in compiler.results_iter():   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 775, in results_iter     rows in self.execute_sql(multi):   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 840, in execute_sql     cursor.execute(sql, params)   file "/home/wesley/howl/debug_toolbar/utils/tracking/db.py", line 134, in execute     template_info = get_template_info(node.source)   file "/home/wesley/howl/debug_toolbar/utils/__init__.py", line 80, in get_template_info     template_source = origin.reload()   file "/home/wesley/environments/howl/local/lib/python2.7/site-packages/django/template/loader.py", line 80, in reload     return self.loader(self.loadname, self.dirs)[0]   file "/home/wesley/howl/dbtemplates/loader.py", line 19, in load_template_source     logger.debug(''.join(traceback.format_stack()))  [...] 

i reproduced project without problem.

the loader called once without recursion. added simple necessary files: videos/models.py , videos/admin.py, dbtemplates/admin.py in order add 2 records video , 1 record template loops on videos: {% video in videos %}...{% endfor %}

i still can not believe recursion possible in loader.load_template_source(). more information necessary. try traceback every call of loader adding these 2 lines it:

... logger.debug('loader.load_template_source......') import traceback                                  # added logger.debug(''.join(traceback.format_stack())) ... 

(i afraid loop or recursion originated in other code spawned many threads wait before database operation until running operation finished.)


edit: problem caused django-debug-toolbar.

  • the database cursor wrapped debug_toolbar monitoring code.
  • it tries introspect stack template_info of template used render.
  • template_info uses template reloading.
  • that again needs access database.

you can disable parts of debug toolbar related database or templates (not tested helps) or disable completely. database operations monitored django , same done debug toolbar less important now.


Comments

Popular posts from this blog

java - Jmockit String final length method mocking Issue -

asp.net - Razor Page Hosted on IIS 6 Fails Every Morning -

c++ - wxwidget compiling on windows command prompt -