Projet

Général

Profil

0001-fields-add-support-for-card-data-sources-to-computed.patch

Frédéric Péters, 26 novembre 2021 13:46

Télécharger (8,41 ko)

Voir les différences:

Subject: [PATCH] fields: add support for card data sources to computed fields
 (#58913)

 tests/form_pages/test_computed_field.py | 47 ++++++++++++
 wcs/fields.py                           | 15 +++-
 wcs/variables.py                        | 96 ++++++++++++++-----------
 3 files changed, 115 insertions(+), 43 deletions(-)
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
-