misc: revamp template complex data handling to monkeypatch last step (#49948)

This commit is contained in:
Frédéric Péters 2021-01-07 23:18:47 +01:00
parent 5707c570b5
commit f356a18261
5 changed files with 41 additions and 20 deletions

View File

@ -2243,7 +2243,11 @@ def test_webservice_with_complex_data(http_requests, pub):
'item_raw': '{{ form_var_item_raw }}',
'ezt_item_raw': '[form_var_item_raw]',
'items_raw': '{{ form_var_items_raw }}',
'with_items_raw': '{% with x=form_var_items_raw %}{{ x }}{% endwith %}',
'with_items_upper': '{% with x=form_var_items_raw %}{{ x.1|upper }}{% endwith %}',
'ezt_items_raw': '[form_var_items_raw]',
'joined_items_raw': '{{ form_var_items_raw|join:"|" }}',
'forloop_items_raw': '{% for item in form_var_items_raw %}{{item}}|{% endfor %}',
}
pub.substitutions.feed(formdata)
with get_publisher().complex_data():
@ -2259,7 +2263,11 @@ def test_webservice_with_complex_data(http_requests, pub):
'item_raw': 'a',
'ezt_item_raw': 'a',
'items_raw': ['a', 'b'],
'ezt_items_raw': ['a', 'b'],
'with_items_raw': ['a', 'b'],
'with_items_upper': 'B',
'ezt_items_raw': repr(['a', 'b']),
'joined_items_raw': 'a|b',
'forloop_items_raw': 'a|b|',
}

View File

@ -17,6 +17,8 @@
import threading
import types
import django.template.base
import django.template.defaulttags
from django.utils import six
from django.utils.six.moves.urllib import parse as urlparse
@ -106,3 +108,18 @@ for key, value in list(locals().items()):
if type(value) in (types.FunctionType,) + six.class_types:
setattr(quixote, key, value)
setattr(quixote.publish, key, value)
if not hasattr(django.template.base, '_monkeypatched'):
# patch render_value_in_context function to add a complex data mark when
# "printing" variables.
django.template.base._monkeypatched = True
orig_render_value_in_context = django.template.base.render_value_in_context
def new_render_value_in_context(value, context):
if 'allow_complex' in context and not isinstance(value, str):
return get_publisher().cache_complex_data(value)
return orig_render_value_in_context(value, context)
django.template.base.render_value_in_context = new_render_value_in_context
django.template.defaulttags.render_value_in_context = new_render_value_in_context

View File

@ -392,7 +392,7 @@ class WcsPublisher(StubWcsPublisher):
finally:
self.complex_data_cache = None
def cache_complex_data(self, value, str_value=None):
def cache_complex_data(self, value):
# Keep a temporary cache of assocations between a complex data value
# (value) and a string reprensentation (str(value) or the dedicated
# str_value parameter).
@ -402,10 +402,9 @@ class WcsPublisher(StubWcsPublisher):
if self.complex_data_cache is None:
# it doesn't do anything unless initialized.
return str_value or value
return value
if str_value is None:
str_value = str(value)
str_value = str(value)
str_value += chr(0xE000 + len(self.complex_data_cache))
self.complex_data_cache[str_value] = value
return str_value
@ -413,7 +412,11 @@ class WcsPublisher(StubWcsPublisher):
def get_cached_complex_data(self, value):
if not isinstance(value, str):
return value
return (self.complex_data_cache or {}).get(value)
value_ = (self.complex_data_cache or {}).get(value)
if hasattr(value_, 'get_value'):
# unlazy variable
return value_.get_value()
return value_
set_publisher_class(WcsPublisher)

View File

@ -520,9 +520,7 @@ class Template(object):
ezt_raises(e)
else:
return self.value
if context.get('allow_complex'):
return fd.getvalue()
return re.sub(r'[\uE000-\uF8FF]', '', force_str(fd.getvalue()))
return force_str(fd.getvalue())
@classmethod
def is_template_string(cls, string):

View File

@ -624,8 +624,7 @@ class LazyFieldVar(object):
@property
def raw(self):
if self._field.store_display_value or self._field.key in ('file', 'date'):
raw_value = self._data.get(self._field.id)
return get_publisher().cache_complex_data(raw_value)
return self._data.get(self._field.id)
raise AttributeError('raw')
def get_value(self):
@ -639,10 +638,7 @@ class LazyFieldVar(object):
return value
def __str__(self):
value = self.get_value()
if not isinstance(value, six.string_types):
value = get_publisher().cache_complex_data(value)
return force_str(value)
return force_str(self.get_value())
def __nonzero__(self):
if self._field.key == 'bool':
@ -942,11 +938,10 @@ class LazyFieldVarBlock(LazyFieldVar):
def get_value(self):
# don't give access to underlying data dictionary.
value = self._data.get(str(self._field.id))
str_value = self._data.get('%s_display' % self._field.id, '---')
if not value:
return str_value
return get_publisher().cache_complex_data(value, str_value)
return self._data.get(str(self._field.id))
def __str__(self):
return self._data.get('%s_display' % self._field.id, '---')
def __getitem__(self, key):
try: