Fixed #18773 -- Added logging for template variable resolving
Added a django.template logger without a default handler. Added logging if there is an exception while resolving variables in a template.
This commit is contained in:
parent
0c91a419f8
commit
dc5b01ad05
|
@ -121,6 +121,7 @@ class AdminField(object):
|
||||||
self.field = form[field] # A django.forms.BoundField instance
|
self.field = form[field] # A django.forms.BoundField instance
|
||||||
self.is_first = is_first # Whether this field is first on the line
|
self.is_first = is_first # Whether this field is first on the line
|
||||||
self.is_checkbox = isinstance(self.field.field.widget, forms.CheckboxInput)
|
self.is_checkbox = isinstance(self.field.field.widget, forms.CheckboxInput)
|
||||||
|
self.is_readonly = False
|
||||||
|
|
||||||
def label_tag(self):
|
def label_tag(self):
|
||||||
classes = []
|
classes = []
|
||||||
|
|
|
@ -51,6 +51,7 @@ u'<html></html>'
|
||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import logging
|
||||||
import re
|
import re
|
||||||
import warnings
|
import warnings
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
@ -125,6 +126,8 @@ libraries = {}
|
||||||
# global list of libraries to load by default for a new parser
|
# global list of libraries to load by default for a new parser
|
||||||
builtins = []
|
builtins = []
|
||||||
|
|
||||||
|
logger = logging.getLogger('django.template')
|
||||||
|
|
||||||
|
|
||||||
class TemplateSyntaxError(Exception):
|
class TemplateSyntaxError(Exception):
|
||||||
pass
|
pass
|
||||||
|
@ -209,6 +212,7 @@ class Template(object):
|
||||||
try:
|
try:
|
||||||
if context.template is None:
|
if context.template is None:
|
||||||
with context.bind_template(self):
|
with context.bind_template(self):
|
||||||
|
context.template_name = self.name
|
||||||
return self._render(context)
|
return self._render(context)
|
||||||
else:
|
else:
|
||||||
return self._render(context)
|
return self._render(context)
|
||||||
|
@ -893,6 +897,9 @@ class Variable(object):
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
template_name = getattr(context, 'template_name', 'unknown')
|
||||||
|
logger.debug('{} - {}'.format(template_name, e))
|
||||||
|
|
||||||
if getattr(e, 'silent_variable_failure', False):
|
if getattr(e, 'silent_variable_failure', False):
|
||||||
current = context.template.engine.string_if_invalid
|
current = context.template.engine.string_if_invalid
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -141,6 +141,7 @@ class Context(BaseContext):
|
||||||
self._current_app = current_app
|
self._current_app = current_app
|
||||||
self.use_l10n = use_l10n
|
self.use_l10n = use_l10n
|
||||||
self.use_tz = use_tz
|
self.use_tz = use_tz
|
||||||
|
self.template_name = "unknown"
|
||||||
self.render_context = RenderContext()
|
self.render_context = RenderContext()
|
||||||
# Set to the original template -- as opposed to extended or included
|
# Set to the original template -- as opposed to extended or included
|
||||||
# templates -- during rendering, see bind_template.
|
# templates -- during rendering, see bind_template.
|
||||||
|
|
|
@ -188,6 +188,9 @@ Templates
|
||||||
* Added a :meth:`Context.setdefault() <django.template.Context.setdefault>`
|
* Added a :meth:`Context.setdefault() <django.template.Context.setdefault>`
|
||||||
method.
|
method.
|
||||||
|
|
||||||
|
* A warning will now be logged for missing context variables. These messages
|
||||||
|
will be logged to the :ref:`django.template <django-template-logger>` logger.
|
||||||
|
|
||||||
Requests and Responses
|
Requests and Responses
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -478,6 +478,16 @@ Messages to this logger have the following extra context:
|
||||||
* ``request``: The request object that generated the logging
|
* ``request``: The request object that generated the logging
|
||||||
message.
|
message.
|
||||||
|
|
||||||
|
.. _django-template-logger:
|
||||||
|
|
||||||
|
``django.template``
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. versionadded:: 1.9
|
||||||
|
|
||||||
|
Log messages related to the rendering of templates. Missing context variables
|
||||||
|
are logged as ``DEBUG`` messages if :setting:`DEBUG` is `True`.
|
||||||
|
|
||||||
.. _django-db-logger:
|
.. _django-db-logger:
|
||||||
|
|
||||||
``django.db.backends``
|
``django.db.backends``
|
||||||
|
|
|
@ -0,0 +1,71 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from django.template import Template, Variable, VariableDoesNotExist
|
||||||
|
from django.test import SimpleTestCase
|
||||||
|
|
||||||
|
|
||||||
|
class TestHandler(logging.Handler):
|
||||||
|
def __init__(self):
|
||||||
|
super(TestHandler, self).__init__()
|
||||||
|
self.log_record = None
|
||||||
|
|
||||||
|
def emit(self, record):
|
||||||
|
self.log_record = record
|
||||||
|
|
||||||
|
|
||||||
|
class VariableResolveLoggingTests(SimpleTestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.test_handler = TestHandler()
|
||||||
|
self.logger = logging.getLogger('django.template')
|
||||||
|
self.original_level = self.logger.level
|
||||||
|
self.logger.addHandler(self.test_handler)
|
||||||
|
self.logger.setLevel(logging.DEBUG)
|
||||||
|
|
||||||
|
def tearDown(self):
|
||||||
|
self.logger.removeHandler(self.test_handler)
|
||||||
|
self.logger.level = self.original_level
|
||||||
|
|
||||||
|
def test_log_on_variable_does_not_exist_silent(self):
|
||||||
|
class TestObject(object):
|
||||||
|
class SilentDoesNotExist(Exception):
|
||||||
|
silent_variable_failure = True
|
||||||
|
|
||||||
|
@property
|
||||||
|
def template_name(self):
|
||||||
|
return "template"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def template(self):
|
||||||
|
return Template('')
|
||||||
|
|
||||||
|
@property
|
||||||
|
def article(self):
|
||||||
|
raise TestObject.SilentDoesNotExist("Attribute does not exist.")
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
return iter(attr for attr in dir(TestObject) if attr[:2] != "__")
|
||||||
|
|
||||||
|
def __getitem__(self, item):
|
||||||
|
return self.__dict__[item]
|
||||||
|
|
||||||
|
Variable('article').resolve(TestObject())
|
||||||
|
self.assertEqual(
|
||||||
|
self.test_handler.log_record.msg,
|
||||||
|
'template - Attribute does not exist.'
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_log_on_variable_does_not_exist_not_silent(self):
|
||||||
|
with self.assertRaises(VariableDoesNotExist):
|
||||||
|
Variable('article.author').resolve({'article': {'section': 'News'}})
|
||||||
|
|
||||||
|
self.assertEqual(
|
||||||
|
self.test_handler.log_record.msg,
|
||||||
|
'unknown - Failed lookup for key [author] in %r' %
|
||||||
|
("{%r: %r}" % ('section', 'News'), )
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_no_log_when_variable_exists(self):
|
||||||
|
Variable('article.section').resolve({'article': {'section': 'News'}})
|
||||||
|
self.assertIsNone(self.test_handler.log_record)
|
Loading…
Reference in New Issue