json cell: add possibility to retrieve data from multiple URLs (#17185)
ex: "metro": { "url": "https://.../stops?identifier=[identifier]", "additional-data": [ {"key": "schedule", "url": "https://.../schedule?stop_identifier=[identifier]" } ] }
This commit is contained in:
parent
4b140eb372
commit
88052430dd
|
@ -832,6 +832,14 @@ class JsonCellBase(CellBase):
|
|||
varnames = None
|
||||
force_async = False
|
||||
actions = {}
|
||||
additional_data = None
|
||||
# [
|
||||
# {'key': ...,
|
||||
# 'url': ...,
|
||||
# 'cache_duration': ... (optional)
|
||||
# },
|
||||
# ...
|
||||
# ]
|
||||
|
||||
_json_content = None
|
||||
|
||||
|
@ -848,28 +856,45 @@ class JsonCellBase(CellBase):
|
|||
if varname in context['request'].GET and varname not in context:
|
||||
context[varname] = context['request'].GET[varname]
|
||||
self._json_content = None
|
||||
extra_context['json'] = None
|
||||
try:
|
||||
url = utils.get_templated_url(self.url, context)
|
||||
except utils.UnknownTemplateVariableError:
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.warning('unknown variable in template URL (%s)', self.url)
|
||||
return extra_context
|
||||
json_response = utils.requests.get(url,
|
||||
headers={'Accept': 'application/json'},
|
||||
remote_service='auto',
|
||||
cache_duration=self.cache_duration,
|
||||
without_user=True,
|
||||
raise_if_not_cached=not(context.get('synchronous')),
|
||||
invalidate_cache=invalidate_cache,
|
||||
)
|
||||
if json_response.status_code == 200:
|
||||
|
||||
data_urls = [{'key': 'json', 'url': self.url, 'cache_duration': self.cache_duration}]
|
||||
data_urls.extend(self.additional_data or [])
|
||||
|
||||
for data_url_dict in data_urls:
|
||||
extra_context[data_url_dict['key']] = None
|
||||
|
||||
for data_url_dict in data_urls:
|
||||
data_key = data_url_dict['key']
|
||||
try:
|
||||
self._json_content = json.loads(json_response.content)
|
||||
except ValueError:
|
||||
url = utils.get_templated_url(data_url_dict['url'], context)
|
||||
except utils.UnknownTemplateVariableError:
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.error('invalid json content (%s)', url)
|
||||
extra_context['json'] = self._json_content
|
||||
logger.warning('unknown variable in template URL (%s)', self.url)
|
||||
continue
|
||||
json_response = utils.requests.get(url,
|
||||
headers={'Accept': 'application/json'},
|
||||
remote_service='auto',
|
||||
cache_duration=data_url_dict.get('cache_duration', self.cache_duration),
|
||||
without_user=True,
|
||||
raise_if_not_cached=not(context.get('synchronous')),
|
||||
invalidate_cache=invalidate_cache,
|
||||
)
|
||||
if json_response.status_code == 200:
|
||||
try:
|
||||
extra_context[data_key] = json.loads(json_response.content)
|
||||
except ValueError:
|
||||
logger = logging.getLogger(__name__)
|
||||
logger.error('invalid json content (%s)', url)
|
||||
continue
|
||||
|
||||
# update context with data key so it can be used in future
|
||||
# templated URLs
|
||||
context[data_key] = extra_context[data_key]
|
||||
|
||||
# keep cache of first response as it may be used to find the
|
||||
# appropriate template.
|
||||
self._json_content = extra_context['json']
|
||||
|
||||
return extra_context
|
||||
|
||||
@property
|
||||
|
@ -1007,6 +1032,10 @@ class ConfigJsonCell(JsonCellBase):
|
|||
return settings.JSON_CELL_TYPES[self.key].get('actions',
|
||||
JsonCellBase.actions)
|
||||
|
||||
@property
|
||||
def additional_data(self):
|
||||
return settings.JSON_CELL_TYPES[self.key].get('additional-data')
|
||||
|
||||
@property
|
||||
def template_name(self):
|
||||
return 'combo/json/%s.html' % self.key
|
||||
|
|
|
@ -364,3 +364,45 @@ def test_json_force_async():
|
|||
assert cell.render(Context({'synchronous': True})) == 'world2'
|
||||
# rerun with stuff in cache
|
||||
assert cell.render(Context({})) == 'world2'
|
||||
|
||||
def test_config_json_cell_additional_url(app):
|
||||
page = Page(title='example page', slug='index')
|
||||
page.save()
|
||||
|
||||
with override_settings(JSON_CELL_TYPES={
|
||||
'test-config-json-cell-2': {
|
||||
'name': 'Foobar',
|
||||
'url': 'http://foo',
|
||||
'additional-data': [
|
||||
{'key': 'plop', 'url': 'http://bar'},
|
||||
]
|
||||
}},
|
||||
TEMPLATE_DIRS=['%s/templates-1' % os.path.abspath(os.path.dirname(__file__))]):
|
||||
cell = ConfigJsonCell()
|
||||
cell.key = 'test-config-json-cell-2'
|
||||
cell.page = page
|
||||
cell.title = 'Example Site'
|
||||
cell.order = 0
|
||||
cell.save()
|
||||
|
||||
with mock.patch('combo.utils.requests.get') as requests_get:
|
||||
data = {'data': 'toto'}
|
||||
requests_get.return_value = mock.Mock(content=json.dumps(data), status_code=200)
|
||||
url = reverse('combo-public-ajax-page-cell',
|
||||
kwargs={'page_pk': page.id, 'cell_reference': cell.get_reference()})
|
||||
resp = app.get(url)
|
||||
assert resp.body.strip() == '/var1=toto/var2=toto/'
|
||||
assert len(requests_get.mock_calls) == 2
|
||||
assert requests_get.mock_calls[0][1][0] == 'http://foo'
|
||||
assert requests_get.mock_calls[1][1][0] == 'http://bar'
|
||||
|
||||
with mock.patch('combo.utils.requests.get') as requests_get:
|
||||
data = {'data': 'toto'}
|
||||
requests_get.return_value = mock.Mock(content=json.dumps(data), status_code=404)
|
||||
url = reverse('combo-public-ajax-page-cell',
|
||||
kwargs={'page_pk': page.id, 'cell_reference': cell.get_reference()})
|
||||
resp = app.get(url)
|
||||
assert resp.body.strip() == '/var1=/var2=/'
|
||||
assert len(requests_get.mock_calls) == 2
|
||||
assert requests_get.mock_calls[0][1][0] == 'http://foo'
|
||||
assert requests_get.mock_calls[1][1][0] == 'http://bar'
|
||||
|
|
Loading…
Reference in New Issue