0001-fields-add-support-for-card-data-sources-to-computed.patch
tests/form_pages/test_computed_field.py | ||
---|---|---|
5 | 5 |
from django.utils.timezone import make_aware |
6 | 6 | |
7 | 7 |
from wcs import fields |
8 |
from wcs.carddef import CardDef |
|
8 | 9 |
from wcs.formdef import FormDef |
9 | 10 |
from wcs.qommon.substitution import CompatibilityNamesDict |
10 | 11 |
from wcs.workflows import EditableWorkflowStatusItem, Workflow |
... | ... | |
586 | 587 |
resp = get_app(pub).get('/test/?param=plop') |
587 | 588 |
resp = resp.forms[0].submit('submit') # -> 2nd page |
588 | 589 |
assert 'count with this value: 0' in resp.text |
590 | ||
591 | ||
592 |
def test_computed_field_with_data_source(pub): |
|
593 |
CardDef.wipe() |
|
594 |
FormDef.wipe() |
|
595 | ||
596 |
carddef = CardDef() |
|
597 |
carddef.name = 'items' |
|
598 |
carddef.digest_templates = {'default': '{{form_var_name}}'} |
|
599 |
carddef.fields = [ |
|
600 |
fields.StringField(id='0', label='string', varname='name'), |
|
601 |
fields.StringField(id='1', label='string', varname='attr'), |
|
602 |
] |
|
603 |
carddef.store() |
|
604 |
for i, value in enumerate(['foo', 'bar', 'baz']): |
|
605 |
carddata = carddef.data_class()() |
|
606 |
carddata.data = { |
|
607 |
'0': value, |
|
608 |
'1': 'attr%s' % i, |
|
609 |
} |
|
610 |
carddata.just_created() |
|
611 |
carddata.store() |
|
612 | ||
613 |
ds = {'type': 'carddef:%s' % carddef.url_name} |
|
614 | ||
615 |
formdef = FormDef() |
|
616 |
formdef.name = 'test' |
|
617 |
formdef.fields = [ |
|
618 |
fields.ComputedField( |
|
619 |
id='1', |
|
620 |
label='computed', |
|
621 |
varname='computed', |
|
622 |
value_template='{{ request.GET.param }}', |
|
623 |
freeze_on_initial_value=True, |
|
624 |
data_source=ds, |
|
625 |
), |
|
626 |
fields.CommentField(id='2', label='X{{ form_var_computed_live_var_name }}Y', type='comment'), |
|
627 |
] |
|
628 |
formdef.store() |
|
629 |
formdef.data_class().wipe() |
|
630 | ||
631 |
resp = get_app(pub).get('/test/?param=%s' % carddata.id) |
|
632 |
assert 'XbazY' in resp.text |
|
633 | ||
634 |
resp = get_app(pub).get('/test/?param=%s' % 'invalid') |
|
635 |
assert 'XY' in resp.text |
wcs/fields.py | ||
---|---|---|
3484 | 3484 | |
3485 | 3485 |
value_template = None |
3486 | 3486 |
freeze_on_initial_value = False |
3487 |
data_source = {} |
|
3487 | 3488 | |
3488 | 3489 |
add_to_form = None |
3489 | 3490 |
add_to_view_form = None |
... | ... | |
3497 | 3498 |
def get_admin_attributes(self): |
3498 | 3499 |
attributes = super().get_admin_attributes() |
3499 | 3500 |
attributes.remove('condition') |
3500 |
return attributes + ['varname', 'value_template', 'freeze_on_initial_value'] |
|
3501 |
return attributes + ['varname', 'value_template', 'freeze_on_initial_value', 'data_source']
|
|
3501 | 3502 | |
3502 | 3503 |
def fill_admin_form(self, form): |
3503 | 3504 |
form.add(StringWidget, 'label', title=_('Label'), value=self.label, required=True, size=50) |
... | ... | |
3526 | 3527 |
title=_('Freeze on initial value'), |
3527 | 3528 |
value=self.freeze_on_initial_value, |
3528 | 3529 |
) |
3530 |
form.add( |
|
3531 |
data_sources.DataSourceSelectionWidget, |
|
3532 |
'data_source', |
|
3533 |
value=self.data_source, |
|
3534 |
allow_jsonp=False, |
|
3535 |
title=_('Data Source'), |
|
3536 |
hint=_('This will make linked card data available for expressions.'), |
|
3537 |
required=False, |
|
3538 |
) |
|
3539 | ||
3540 |
def get_real_data_source(self): |
|
3541 |
return data_sources.get_real(self.data_source) |
|
3529 | 3542 | |
3530 | 3543 | |
3531 | 3544 |
register_field_class(ComputedField) |
wcs/variables.py | ||
---|---|---|
844 | 844 |
raise KeyError(key) |
845 | 845 | |
846 | 846 | |
847 |
class LazyFieldVarComputed(LazyFieldVarComplex): |
|
847 |
class LazyFieldVarLiveCardMixin: |
|
848 |
@property |
|
849 |
def live(self): |
|
850 |
real_data_source = self._field.get_real_data_source() |
|
851 |
if not ( |
|
852 |
real_data_source |
|
853 |
and ( |
|
854 |
real_data_source.get('type', '').startswith('carddef:') |
|
855 |
or real_data_source.get('type', '') == 'wcs:users' |
|
856 |
) |
|
857 |
): |
|
858 |
raise AttributeError('live') |
|
859 |
if real_data_source.get('type', '') == 'wcs:users': |
|
860 |
return LazyUser(get_publisher().user_class.get(self._data.get(self._field.id))) |
|
861 |
request = get_request() |
|
862 |
card_id = self._data.get(self._field.id) |
|
863 |
if request: |
|
864 |
# cache during request |
|
865 |
cache_key = '%s-%s' % (self._field.data_source['type'], card_id) |
|
866 |
if not hasattr(request, 'live_card_cache'): |
|
867 |
request.live_card_cache = {} |
|
868 |
else: |
|
869 |
carddata = request.live_card_cache.get(cache_key) |
|
870 |
if carddata is not None: |
|
871 |
# cached data |
|
872 |
if isinstance(carddata, Exception): |
|
873 |
raise carddata |
|
874 |
return LazyFormData(carddata) |
|
875 |
from wcs.carddef import CardDef |
|
876 | ||
877 |
try: |
|
878 |
carddef = CardDef.get_by_urlname(self._field.data_source['type'].split(':')[1]) |
|
879 |
carddata = carddef.data_class().get(card_id) |
|
880 |
if request: |
|
881 |
request.live_card_cache[cache_key] = carddata |
|
882 |
except KeyError: |
|
883 |
if request: |
|
884 |
request.live_card_cache[cache_key] = AttributeError('live') |
|
885 |
raise AttributeError('live') |
|
886 |
return LazyFormData(carddata) |
|
887 | ||
888 | ||
889 |
class LazyFieldVarComputed(LazyFieldVarComplex, LazyFieldVarLiveCardMixin): |
|
890 |
def inspect_keys(self): |
|
891 |
keys = super().inspect_keys() |
|
892 |
try: |
|
893 |
self.live |
|
894 |
except AttributeError: |
|
895 |
pass # don't advertise if there's no value behind |
|
896 |
else: |
|
897 |
keys.append('live') |
|
898 |
return keys |
|
899 | ||
848 | 900 |
def get_field_var_value(self): |
849 | 901 |
return self.get_value() |
850 | 902 | |
851 | 903 | |
852 |
class LazyFieldVarStructured(LazyFieldVarComplex): |
|
904 |
class LazyFieldVarStructured(LazyFieldVarComplex, LazyFieldVarLiveCardMixin):
|
|
853 | 905 |
def inspect_keys(self): |
854 | 906 |
if not self._data.get(self._field.id): |
855 | 907 |
return [] |
... | ... | |
887 | 939 |
def get_field_var_value(self): |
888 | 940 |
return self.structured |
889 | 941 | |
890 |
@property |
|
891 |
def live(self): |
|
892 |
real_data_source = self._field.get_real_data_source() |
|
893 |
if not ( |
|
894 |
real_data_source |
|
895 |
and ( |
|
896 |
real_data_source.get('type', '').startswith('carddef:') |
|
897 |
or real_data_source.get('type', '') == 'wcs:users' |
|
898 |
) |
|
899 |
): |
|
900 |
raise AttributeError('live') |
|
901 |
if real_data_source.get('type', '') == 'wcs:users': |
|
902 |
return LazyUser(get_publisher().user_class.get(self._data.get(self._field.id))) |
|
903 |
request = get_request() |
|
904 |
card_id = self._data.get(self._field.id) |
|
905 |
if request: |
|
906 |
# cache during request |
|
907 |
cache_key = '%s-%s' % (self._field.data_source['type'], card_id) |
|
908 |
if not hasattr(request, 'live_card_cache'): |
|
909 |
request.live_card_cache = {} |
|
910 |
else: |
|
911 |
carddata = request.live_card_cache.get(cache_key) |
|
912 |
if carddata is not None: |
|
913 |
# cached data |
|
914 |
if isinstance(carddata, Exception): |
|
915 |
raise carddata |
|
916 |
return LazyFormData(carddata) |
|
917 |
from wcs.carddef import CardDef |
|
918 | ||
919 |
try: |
|
920 |
carddef = CardDef.get_by_urlname(self._field.data_source['type'].split(':')[1]) |
|
921 |
carddata = carddef.data_class().get(card_id) |
|
922 |
if request: |
|
923 |
request.live_card_cache[cache_key] = carddata |
|
924 |
except KeyError: |
|
925 |
if request: |
|
926 |
request.live_card_cache[cache_key] = AttributeError('live') |
|
927 |
raise AttributeError('live') |
|
928 |
return LazyFormData(carddata) |
|
929 | ||
930 | 942 | |
931 | 943 |
class DateOperatorsMixin: |
932 | 944 |
def __eq__(self, other): |
933 |
- |