Projet

Général

Profil

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

Frédéric Péters, 26 juin 2017 10:19

Télécharger (6,34 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 | 69 ++++++++++++++++++++++++++++++++++++----------------
 tests/test_cells.py  | 30 +++++++++++++++++++++++
 2 files changed, 78 insertions(+), 21 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
                return extra_context
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
                    break
889

  
890
            # update context with data key so it can be used in future
891
            # templated URLs
892
            context[data_key] = extra_context[data_key]
893

  
894
        self._json_content = extra_context['json']
895

  
873 896
        return extra_context
874 897

  
875 898
    @property
......
1004 1027
                JsonCellBase.actions)
1005 1028

  
1006 1029
    @property
1030
    def additional_data(self):
1031
        return settings.JSON_CELL_TYPES[self.key].get('additional-data')
1032

  
1033
    @property
1007 1034
    def template_name(self):
1008 1035
        return 'combo/json/%s.html' % self.key
1009 1036

  
......
1019 1046
        return config_form_class
1020 1047

  
1021 1048
    def get_cell_extra_context(self, context, **kwargs):
1022
        context.update(self.parameters) # early push for templated URLs
1049
        context.update(copy.copy(self.parameters)) # early push for templated URLs
1023 1050
        ctx = super(ConfigJsonCell, self).get_cell_extra_context(context, **kwargs)
1024 1051
        ctx['parameters'] = self.parameters
1025 1052
        ctx.update(self.parameters)
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
-