misc: use django rendition of variables as complex data string values (#50181)

This commit is contained in:
Frédéric Péters 2021-01-17 11:56:16 +01:00
parent d9aa4149a2
commit c546d5a122
3 changed files with 51 additions and 7 deletions

View File

@ -2253,6 +2253,7 @@ def test_webservice_with_complex_data(http_requests, pub):
'forloop_items_raw': '{% for item in form_var_items_raw %}{{item}}|{% endfor %}',
'str': '{{ form_var_str }}',
'str_mod': '{{ form_var_str }}--plop',
'decimal': '{{ "1000"|decimal }}',
}
pub.substitutions.feed(formdata)
with get_publisher().complex_data():
@ -2275,6 +2276,7 @@ def test_webservice_with_complex_data(http_requests, pub):
'forloop_items_raw': 'a|b|',
'str': 'tutuche',
'str_mod': 'tutuche--plop',
'decimal': '1000',
}
# check it's possible to disable complex data support
@ -4023,6 +4025,46 @@ def test_set_backoffice_field(http_requests, two_pubs):
assert logged_error.exception_message.startswith('syntax error in Django template')
def test_set_backoffice_field_decimal(http_requests, two_pubs):
Workflow.wipe()
FormDef.wipe()
if two_pubs.is_using_postgresql():
two_pubs.loggederror_class.wipe()
wf = Workflow(name='xxx')
wf.backoffice_fields_formdef = WorkflowBackofficeFieldsFormDef(wf)
wf.backoffice_fields_formdef.fields = [
StringField(id='bo1', label='1st backoffice field',
type='string', varname='backoffice_blah'),
]
st1 = wf.add_status('Status1')
wf.store()
formdef = FormDef()
formdef.name = 'baz'
formdef.fields = [
StringField(id='1', label='String', type='string', varname='string'),
]
formdef.workflow_id = wf.id
formdef.store()
formdata = formdef.data_class()()
formdata.data = {'1': '1000'}
formdata.just_created()
formdata.store()
two_pubs.substitutions.feed(formdata)
item = SetBackofficeFieldsWorkflowStatusItem()
item.parent = st1
item.fields = [{'field_id': 'bo1', 'value': '{{ "100"|decimal }}'}]
item.perform(formdata)
assert formdef.data_class().get(formdata.id).data['bo1'] == '100'
formdata.store() # reset
item.fields = [{'field_id': 'bo1', 'value': '{{ form_var_string|decimal }}'}]
item.perform(formdata)
assert formdef.data_class().get(formdata.id).data['bo1'] == '1000'
def test_set_backoffice_field_file(http_requests, two_pubs):
Workflow.wipe()
FormDef.wipe()

View File

@ -117,9 +117,10 @@ if not hasattr(django.template.base, '_monkeypatched'):
orig_render_value_in_context = django.template.base.render_value_in_context
def new_render_value_in_context(value, context):
rendered_value = orig_render_value_in_context(value, context)
if context.get('allow_complex') and not isinstance(value, str):
return get_publisher().cache_complex_data(value)
return orig_render_value_in_context(value, context)
return get_publisher().cache_complex_data(value, rendered_value)
return rendered_value
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

@ -15,6 +15,7 @@
# along with this program; if not, see <http://www.gnu.org/licenses/>.
from contextlib import contextmanager
import decimal
import json
import os
import random
@ -26,6 +27,7 @@ import zipfile
from django.utils import six
from django.utils.encoding import force_text
from django.utils.formats import localize
from django.utils.six.moves import cPickle
from .Defaults import *
@ -394,10 +396,10 @@ class WcsPublisher(StubWcsPublisher):
finally:
self.complex_data_cache = None
def cache_complex_data(self, value):
def cache_complex_data(self, value, rendered_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).
# (value) and a string reprensentation (produced by django with
# django.template.base.render_value_in_context.
#
# It ensures string values are unique by appending a private unicode
# code point, that will be removed in wcs/qommon/template.py.
@ -406,8 +408,7 @@ class WcsPublisher(StubWcsPublisher):
# it doesn't do anything unless initialized.
return value
str_value = str(value)
str_value += chr(0xE000 + len(self.complex_data_cache))
str_value = rendered_value + chr(0xE000 + len(self.complex_data_cache))
self.complex_data_cache[str_value] = value
return str_value