Projet

Général

Profil

0001-json-cell-add-possibility-to-retrieve-data-from-mult.patch

Thomas Noël, 19 juillet 2017 15:19

Télécharger (5,97 ko)

Voir les différences:

Subject: [PATCH] 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]"
       }
    ]
  }
 combo/data/models.py | 67 ++++++++++++++++++++++++++++++++++++----------------
 tests/test_cells.py  | 30 +++++++++++++++++++++++
 2 files changed, 77 insertions(+), 20 deletions(-)
combo/data/models.py
832 832
    varnames = None
833 833
    force_async = False
834 834
    actions = {}
835
    additional_data = None
836
        # [
837
        #  {'key': ...,
838
        #   'url': ...,
839
        #   'cache_duration': ... (optional)
840
        #  },
841
        #  ...
842
        # ]
835 843

  
836 844
    _json_content = None
837 845

  
......
848 856
                if varname in context['request'].GET and varname not in context:
849 857
                    context[varname] = context['request'].GET[varname]
850 858
        self._json_content = None
851
        extra_context['json'] = None
852
        try:
853
            url = utils.get_templated_url(self.url, context)
854
        except utils.UnknownTemplateVariableError:
855
            logger = logging.getLogger(__name__)
856
            logger.warning('unknown variable in template URL (%s)', self.url)
857
            return extra_context
858
        json_response = utils.requests.get(url,
859
                headers={'Accept': 'application/json'},
860
                remote_service='auto',
861
                cache_duration=self.cache_duration,
862
                without_user=True,
863
                raise_if_not_cached=not(context.get('synchronous')),
864
                invalidate_cache=invalidate_cache,
865
                )
866
        if json_response.status_code == 200:
859

  
860
        data_urls = [{'key': 'json', 'url': self.url, 'cache_duration': self.cache_duration}]
861
        data_urls.extend(self.additional_data or [])
862

  
863
        for data_url_dict in data_urls:
864
            extra_context[data_url_dict['key']] = None
865

  
866
        for data_url_dict in data_urls:
867
            data_key = data_url_dict['key']
867 868
            try:
868
                self._json_content = json.loads(json_response.content)
869
            except ValueError:
869
                url = utils.get_templated_url(data_url_dict['url'], context)
870
            except utils.UnknownTemplateVariableError:
870 871
                logger = logging.getLogger(__name__)
871
                logger.error('invalid json content (%s)', url)
872
        extra_context['json'] = self._json_content
872
                logger.warning('unknown variable in template URL (%s)', self.url)
873
                continue
874
            json_response = utils.requests.get(url,
875
                    headers={'Accept': 'application/json'},
876
                    remote_service='auto',
877
                    cache_duration=data_url_dict.get('cache_duration', self.cache_duration),
878
                    without_user=True,
879
                    raise_if_not_cached=not(context.get('synchronous')),
880
                    invalidate_cache=invalidate_cache,
881
                    )
882
            if json_response.status_code == 200:
883
                try:
884
                    extra_context[data_key] = json.loads(json_response.content)
885
                except ValueError:
886
                    logger = logging.getLogger(__name__)
887
                    logger.error('invalid json content (%s)', url)
888
                    continue
889
                # update context with data key so it can be used in future
890
                # templated URLs
891
                context[data_key] = extra_context[data_key]
892

  
893
        # keep cache of first response as it may be used to find the
894
        # appropriate template.
895
        self._json_content = extra_context['json']
873 896
        return extra_context
874 897

  
875 898
    @property
......
1008 1031
                JsonCellBase.actions)
1009 1032

  
1010 1033
    @property
1034
    def additional_data(self):
1035
        return settings.JSON_CELL_TYPES[self.key].get('additional-data')
1036

  
1037
    @property
1011 1038
    def template_name(self):
1012 1039
        return 'combo/json/%s.html' % self.key
1013 1040

  
tests/test_cells.py
364 364
        assert cell.render(Context({'synchronous': True})) == 'world2'
365 365
        # rerun with stuff in cache
366 366
        assert cell.render(Context({})) == 'world2'
367

  
368
def test_config_json_cell_additional_url(app):
369
    page = Page(title='example page', slug='index')
370
    page.save()
371

  
372
    with override_settings(JSON_CELL_TYPES={
373
            'test-config-json-cell': {
374
                'name': 'Foobar',
375
                'url': 'http://foo',
376
                'additional-data': [
377
                    {'key': 'plop', 'url': 'http://bar'},
378
                ]
379
            }},
380
            TEMPLATE_DIRS=['%s/templates-1' % os.path.abspath(os.path.dirname(__file__))]):
381
        cell = ConfigJsonCell()
382
        cell.key = 'test-config-json-cell'
383
        cell.page = page
384
        cell.title = 'Example Site'
385
        cell.order = 0
386
        cell.save()
387

  
388
        with mock.patch('combo.utils.requests.get') as requests_get:
389
            data = {'data': 'toto'}
390
            requests_get.return_value = mock.Mock(content=json.dumps(data), status_code=200)
391
            url = reverse('combo-public-ajax-page-cell',
392
                kwargs={'page_pk': page.id, 'cell_reference': cell.get_reference()})
393
            resp = app.get(url)
394
            assert len(requests_get.mock_calls) == 2
395
            assert requests_get.mock_calls[0][1][0] == 'http://foo'
396
            assert requests_get.mock_calls[1][1][0] == 'http://bar'
367
-