diff --git a/tests/test_formdata.py b/tests/test_formdata.py index 37360038e..012cc0b6c 100644 --- a/tests/test_formdata.py +++ b/tests/test_formdata.py @@ -1046,7 +1046,56 @@ def test_lazy_formdata_live_user_item(pub, local_user): assert 'form_var_foo_live_email' in context.get_flat_keys() -def test_lazy_formdata_user_items(pub, local_user): +def test_lazy_formdata_card_live_items(pub): + CardDef.wipe() + carddef = CardDef() + carddef.name = 'items' + carddef.digest_templates = {'default': '{{form_var_name}}'} + carddef.fields = [ + fields.StringField(id='0', label='string', varname='name'), + fields.StringField(id='1', label='string', varname='attr'), + ] + carddef.store() + for i, value in enumerate(['foo', 'bar', 'baz']): + carddata = carddef.data_class()() + carddata.data = { + '0': value, + '1': 'attr%s' % i, + } + carddata.just_created() + carddata.store() + + ds = {'type': 'carddef:%s' % carddef.url_name} + formdef = FormDef() + formdef.name = 'foobar' + formdef.fields = [ + fields.ItemsField( + id='0', label='items', type='items', varname='foo', data_source=ds, display_disabled_items=True + ) + ] + formdef.store() + + formdata = formdef.data_class()() + formdata.data = { + '0': [str(carddata.id)], + } + formdata.data['0_display'] = formdef.fields[0].store_display_value(formdata.data, '0') + formdata.data['0_structured'] = formdef.fields[0].store_structured_value(formdata.data, '0') + pub.substitutions.feed(pub) + pub.substitutions.feed(formdef) + pub.substitutions.feed(formdata) + + context = pub.substitutions.get_context_variables(mode='lazy') + assert [context[k] for k in context.get_flat_keys()] + assert context['form_var_foo_live_0_name'] == 'items' + assert context['form_var_foo_live_0_number'] == carddata.get_display_id() + assert context['form_var_foo_live_0_var_name'] == 'baz' + assert context['form_var_foo_live_0_var_attr'] == 'attr2' + with pytest.raises(KeyError): + assert context['form_var_foo_live_1_var_attr'] + + +def test_lazy_formdata_user_live_items(pub, local_user): NamedDataSource.wipe() datasource = NamedDataSource(name='foo') datasource.data_source = {'type': 'wcs:users'} @@ -1084,6 +1133,8 @@ def test_lazy_formdata_user_items(pub, local_user): context = pub.substitutions.get_context_variables(mode='lazy') assert [context[k] for k in context.get_flat_keys()] + assert context['form_var_foo_live_0_email'] == local_user.email + assert context['form_var_foo_live_1_email'] == user2.email def test_lazy_formdata_queryset(pub, variable_test_data): diff --git a/wcs/variables.py b/wcs/variables.py index a50910d73..f6df9a41b 100644 --- a/wcs/variables.py +++ b/wcs/variables.py @@ -901,6 +901,16 @@ class LazyFieldVar: class LazyFieldVarComplex(LazyFieldVar): + def has_live_data_source(self): + real_data_source = self._field.get_real_data_source() + if not real_data_source: + return False + if real_data_source.get('type', '') == 'wcs:users': + return True + if real_data_source.get('type', '').startswith('carddef:'): + return True + return False + def inspect_keys(self): keys = [] structured_value = self.get_field_var_value() @@ -939,6 +949,9 @@ class LazyFieldVarComplex(LazyFieldVar): class LazyFieldVarLiveCardMixin: + def get_data_id(self): + return self._data.get(self._field.id) + @property def live(self): real_data_source = self._field.get_real_data_source() @@ -951,9 +964,9 @@ class LazyFieldVarLiveCardMixin: ): raise AttributeError('live') if real_data_source.get('type', '') == 'wcs:users': - return LazyUser(get_publisher().user_class.get(self._data.get(self._field.id))) + return LazyUser(get_publisher().user_class.get(self.get_data_id())) request = get_request() - card_id = self._data.get(self._field.id) + card_id = self.get_data_id() if request: # cache during request cache_key = '%s-%s' % (self._field.data_source['type'], card_id) @@ -1002,7 +1015,7 @@ class LazyFieldVarStructured(LazyFieldVarComplex, LazyFieldVarLiveCardMixin): real_data_source = self._field.get_real_data_source() if ( real_data_source - and self._field.type == 'item' + and self._field.type in ('item', 'items') and real_data_source.get('type', '') == 'wcs:users' ): return ['raw', 'live'] @@ -1014,7 +1027,7 @@ class LazyFieldVarStructured(LazyFieldVarComplex, LazyFieldVarLiveCardMixin): keys = ['raw', 'structured'] if ( real_data_source - and self._field.type == 'item' + and self._field.type in ('item', 'items') and real_data_source.get('type', '').startswith('carddef:') ): try: @@ -1148,7 +1161,47 @@ class LazyFieldVarMap(LazyFieldVarStructured): return ['lat', 'lon'] if self.get_field_var_value() else [] +class LazyFieldVarLiveSequenceItem(LazyFieldVarLiveCardMixin): + def __init__(self, field, data, idx): + self._field = field + self._data = data + self.idx = idx + + def get_data_id(self): + return self._data.get(self._field.id)[self.idx] + + +class LazyFieldVarLiveSequence: + def __init__(self, field, data): + self._field = field + self._data = data + self._list = data.get(self._field.id) or [] + + def inspect_keys(self): + return [str(i) for i in range(len(self))] + + def __len__(self): + return len(self._list) + + def __iter__(self): + yield from self._list + + def __getitem__(self, key): + try: + key = int(key) + except ValueError: + raise KeyError(key) + try: + return LazyFieldVarLiveSequenceItem(self._field, self._data, key).live + except IndexError: + raise KeyError(key) + + class LazyFieldVarItems(LazyFieldVarStructured): + @property + def live(self): + return LazyFieldVarLiveSequence(self._field, self._data) + def getlist(self, key): structured_value = self.structured if structured_value: