Projet

Général

Profil

0001-misc-add-with_custom_view-filter-48553.patch

Lauréline Guérin, 19 novembre 2020 14:24

Télécharger (14,2 ko)

Voir les différences:

Subject: [PATCH] misc: add with_custom_view filter (#48553)

 tests/test_carddef.py             | 68 ++++++++++++++++++++++++++--
 tests/test_formdata.py            | 74 ++++++++++++++++++++++++++-----
 wcs/carddef.py                    | 23 +---------
 wcs/custom_views.py               | 26 ++++++++++-
 wcs/qommon/templatetags/qommon.py |  7 ++-
 wcs/variables.py                  | 13 ++++++
 6 files changed, 172 insertions(+), 39 deletions(-)
tests/test_carddef.py
223 223
    carddef.name = 'foo'
224 224
    carddef.fields = [
225 225
        StringField(id='1', label='Test', type='string', varname='foo'),
226
        StringField(id='2', label='key', type='string', varname='key'),
226 227
    ]
227 228
    carddef.store()
228 229
    carddef.data_class().wipe()
229 230

  
230 231
    for i in range(10):
231 232
        carddata = carddef.data_class()()
232
        carddata.data = {'1': 'blah'}
233
        if i % 3 == 0:
234
            carddata.data = {'1': 'blah'}
235
        if i % 3 == 1:
236
            carddata.data = {'1': 'foo'}
237
        if i % 3 == 2:
238
            carddata.data = {'1': 'bar'}
239
        carddata.data['2'] = str(i)
233 240
        carddata.just_created()
234 241
        carddata.store()
235 242

  
236 243
    context = pub.substitutions.get_context_variables(mode='lazy')
237
    tmpl = Template('{{cards.foo.objects|filter_by:"foo"|filter_value:"blah"|count}}')
238
    assert tmpl.render(context) == '10'
239 244

  
245
    tmpl = Template('{{cards.foo.objects|filter_by:"foo"|filter_value:"blah"|count}}')
246
    assert tmpl.render(context) == '4'
240 247
    tmpl = Template('{{cards|objects:"foo"|filter_by:"foo"|filter_value:"blah"|count}}')
241
    assert tmpl.render(context) == '10'
248
    assert tmpl.render(context) == '4'
249

  
250
    pub.custom_view_class.wipe()
251

  
252
    custom_view1 = pub.custom_view_class()
253
    custom_view1.title = 'datasource card view'
254
    custom_view1.formdef = carddef
255
    custom_view1.columns = {'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}]}
256
    custom_view1.filters = {'filter-1': 'on', 'filter-1-value': 'blah'}
257
    custom_view1.visibility = 'datasource'
258
    custom_view1.order_by = '-f2'
259
    custom_view1.store()
260

  
261
    custom_view2 = pub.custom_view_class()
262
    custom_view2.title = 'shared card view'
263
    custom_view2.formdef = carddef
264
    custom_view2.columns = {'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}]}
265
    custom_view2.filters = {'filter-1': 'on', 'filter-1-value': 'foo'}
266
    custom_view2.visibility = 'any'
267
    custom_view2.order_by = 'f2'
268
    custom_view2.store()
269

  
270
    custom_view3 = pub.custom_view_class()
271
    custom_view3.title = 'private card view'
272
    custom_view3.formdef = carddef
273
    custom_view3.columns = {'list': [{'id': 'id'}]}
274
    custom_view3.filters = {}
275
    custom_view3.visibility = 'owner'
276
    custom_view3.usier_id = 42
277
    custom_view3.order_by = 'id'
278
    custom_view3.store()
279

  
280
    tmpl = Template('{{cards.foo.objects|with_custom_view:"datasource-card-view"|count}}')
281
    assert tmpl.render(context) == '4'
282
    tmpl = Template('{{cards|objects:"foo"|with_custom_view:"datasource-card-view"|count}}')
283
    assert tmpl.render(context) == '4'
284
    tmpl = Template('{% for data in cards|objects:"foo"|with_custom_view:"datasource-card-view" %}{{ data.internal_id }},{% endfor %}')
285
    assert tmpl.render(context) == '10,7,4,1,'
286

  
287
    tmpl = Template('{{cards.foo.objects|with_custom_view:"shared-card-view"|count}}')
288
    assert tmpl.render(context) == '3'
289
    tmpl = Template('{{cards|objects:"foo"|with_custom_view:"shared-card-view"|count}}')
290
    assert tmpl.render(context) == '3'
291
    tmpl = Template('{% for data in cards|objects:"foo"|with_custom_view:"shared-card-view" %}{{ data.internal_id }},{% endfor %}')
292
    assert tmpl.render(context) == '2,5,8,'
293

  
294
    tmpl = Template('{{cards.foo.objects|with_custom_view:"private-card-view"|count}}')
295
    assert tmpl.render(context) == '0'
296
    tmpl = Template('{{cards|objects:"foo"|with_custom_view:"private-card-view"|count}}')
297
    assert tmpl.render(context) == '0'
298
    tmpl = Template('{{cards.foo.objects|with_custom_view:"unknown"|count}}')
299
    assert tmpl.render(context) == '0'
300
    tmpl = Template('{{cards|objects:"foo"|with_custom_view:"unknown"|count}}')
301
    assert tmpl.render(context) == '0'
242 302

  
243 303

  
244 304
def test_data_source_access_invalid_id(pub):
tests/test_formdata.py
1134 1134
    assert tmpl.render(context) == 'bar'
1135 1135

  
1136 1136

  
1137
def test_lazy_global_forms(pub, variable_test_data):
1138
    lazy_formdata = variable_test_data
1139
    formdef = lazy_formdata._formdef
1137
def test_lazy_global_forms(pub):
1138
    FormDef.wipe()
1139
    formdef = FormDef()
1140
    formdef.name = 'foobarlazy'
1141
    formdef.fields = [
1142
        fields.StringField(id='1', label='Test', type='string', varname='foo'),
1143
        fields.StringField(id='2', label='key', type='string', varname='key'),
1144
    ]
1140 1145
    formdef.store()
1141
    data_class = lazy_formdata._formdef.data_class()
1146
    formdef.data_class().wipe()
1142 1147
    for i in range(6):
1143
        formdata = data_class()
1144
        formdata.data = {'0': 'bar'}
1148
        formdata = formdef.data_class()()
1149
        formdata.data = {'1': 'bar', '2': str(i)}
1145 1150
        formdata.just_created()
1146 1151
        formdata.store()
1147 1152
    for i in range(4):
1148
        formdata = data_class()
1149
        formdata.data = {'0': 'foo'}
1153
        formdata = formdef.data_class()()
1154
        formdata.data = {'1': 'foo', '2': str(i+6)}
1150 1155
        formdata.just_created()
1151 1156
        formdata.jump_status('finished')
1152 1157
        formdata.store()
1153 1158

  
1154
    formdata = data_class()
1155
    formdata.data = {'0': 'bar'}
1159
    formdata = formdef.data_class()()
1160
    formdata.data = {'1': 'bar'}
1156 1161
    formdata.status = 'draft'
1157 1162
    formdata.store()
1158 1163

  
......
1161 1166
    tmpl = Template('{{forms.foobarlazy.slug}}')
1162 1167
    assert tmpl.render(context) == 'foobarlazy'
1163 1168

  
1164
    tmpl = Template('{{forms|objects:"foobarlazy"|filter_by:"foo_foo"|filter_value:"bar"|count}}')
1165
    assert tmpl.render(context) == '7'
1169
    tmpl = Template('{{forms|objects:"foobarlazy"|filter_by:"foo"|filter_value:"bar"|count}}')
1170
    assert tmpl.render(context) == '6'
1171

  
1172
    pub.custom_view_class.wipe()
1173

  
1174
    custom_view1 = pub.custom_view_class()
1175
    custom_view1.title = 'datasource form view'
1176
    custom_view1.formdef = formdef
1177
    custom_view1.columns = {'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}]}
1178
    custom_view1.filters = {'filter-1': 'on', 'filter-1-value': 'bar'}
1179
    custom_view1.visibility = 'datasource'
1180
    custom_view1.order_by = '-f2'
1181
    custom_view1.store()
1182

  
1183
    custom_view2 = pub.custom_view_class()
1184
    custom_view2.title = 'shared form view'
1185
    custom_view2.formdef = formdef
1186
    custom_view2.columns = {'list': [{'id': 'id'}, {'id': 'time'}, {'id': 'status'}]}
1187
    custom_view2.filters = {'filter-1': 'on', 'filter-1-value': 'foo'}
1188
    custom_view2.visibility = 'any'
1189
    custom_view2.order_by = 'f2'
1190
    custom_view2.store()
1191

  
1192
    custom_view3 = pub.custom_view_class()
1193
    custom_view3.title = 'private form view'
1194
    custom_view3.formdef = formdef
1195
    custom_view3.columns = {'list': [{'id': 'id'}]}
1196
    custom_view3.filters = {}
1197
    custom_view3.visibility = 'owner'
1198
    custom_view3.usier_id = 42
1199
    custom_view3.order_by = 'id'
1200
    custom_view3.store()
1201

  
1202
    tmpl = Template('{{forms|objects:"foobarlazy"|with_custom_view:"datasource-form-view"|count}}')
1203
    assert tmpl.render(context) == '6'
1204
    tmpl = Template('{% for data in forms|objects:"foobarlazy"|with_custom_view:"datasource-form-view" %}{{ data.internal_id }},{% endfor %}')
1205
    assert tmpl.render(context) == '6,5,4,3,2,1,'
1206

  
1207
    tmpl = Template('{{forms|objects:"foobarlazy"|with_custom_view:"shared-form-view"|count}}')
1208
    assert tmpl.render(context) == '4'
1209
    tmpl = Template('{% for data in forms|objects:"foobarlazy"|with_custom_view:"shared-form-view" %}{{ data.internal_id }},{% endfor %}')
1210
    assert tmpl.render(context) == '7,8,9,10,'
1211

  
1212
    tmpl = Template('{{forms|objects:"foobarlazy"|with_custom_view:"private-form-view"|count}}')
1213
    assert tmpl.render(context) == '0'
1214
    tmpl = Template('{{forms|objects:"foobarlazy"|with_custom_view:"unknown"|count}}')
1215
    assert tmpl.render(context) == '0'
1166 1216

  
1167 1217

  
1168 1218
def test_lazy_variables(pub, variable_test_data):
wcs/carddef.py
172 172
        except IndexError:
173 173
            return None
174 174

  
175
    @classmethod
176
    def get_data_source_criterias(cls, carddef, custom_view):
177
        from wcs.backoffice.management import FormPage
178
        form_page = FormPage(formdef=carddef, view=custom_view, update_breadcrumbs=False)
179
        criterias = form_page.get_view_criterias()
180

  
181
        selected_filter = custom_view.get_filter()
182
        if selected_filter and selected_filter != 'all':
183
            if selected_filter == 'pending':
184
                applied_filters = ['wf-%s' % x.id for x in carddef.workflow.get_not_endpoint_status()]
185
            elif selected_filter == 'done':
186
                applied_filters = ['wf-%s' % x.id for x in carddef.workflow.get_endpoint_status()]
187
            else:
188
                applied_filters = ['wf-%s' % selected_filter]
189
            if applied_filters:
190
                criterias.append(Contains('status', applied_filters))
191

  
192
        return criterias
193

  
194 175
    @classmethod
195 176
    def get_data_source_items(cls, data_source_id, query=None, limit=None,
196 177
            custom_view=None, get_by_id=None, get_by_text=None):
......
209 190
                if not custom_view:
210 191
                    return []
211 192
            order_by = custom_view.order_by
212
            criterias.extend(cls.get_data_source_criterias(carddef, custom_view))
193
            criterias.extend(custom_view.get_criterias(formdef=carddef))
213 194
            for criteria in criterias:
214 195
                if not Template.is_template_string(criteria.value):
215 196
                    continue
......
267 248
            return []
268 249
        varnames = []
269 250
        from .fields import Field
270
        for criteria in cls.get_data_source_criterias(carddef, custom_view):
251
        for criteria in custom_view.get_criterias(formdef=carddef):
271 252
            if not isinstance(criteria.value, str):
272 253
                continue
273 254
            varnames.extend(Field.get_referenced_varnames(formdef, criteria.value))
wcs/custom_views.py
22 22

  
23 23
from wcs.carddef import CardDef
24 24
from wcs.formdef import FormDef
25
from wcs.qommon.storage import StorableObject, Equal
25
from wcs.qommon.storage import StorableObject, Equal, Contains
26 26
from wcs.qommon.misc import simplify
27 27
from .qommon.misc import xml_node_text
28 28

  
......
142 142
    def get_default_filters(self):
143 143
        return [key[7:] for key in self.filters if key.startswith('filter-')]
144 144

  
145
    def get_criterias(self, formdef=None):
146
        from wcs.backoffice.management import FormPage
147

  
148
        if formdef is not None:
149
            assert formdef.id == self.formdef_id
150
        else:
151
            formdef = self.formdef
152

  
153
        form_page = FormPage(formdef=formdef, view=self, update_breadcrumbs=False)
154
        criterias = form_page.get_view_criterias()
155

  
156
        selected_filter = self.get_filter()
157
        if selected_filter and selected_filter != 'all':
158
            if selected_filter == 'pending':
159
                applied_filters = ['wf-%s' % x.id for x in formdef.workflow.get_not_endpoint_status()]
160
            elif selected_filter == 'done':
161
                applied_filters = ['wf-%s' % x.id for x in formdef.workflow.get_endpoint_status()]
162
            else:
163
                applied_filters = ['wf-%s' % selected_filter]
164
            if applied_filters:
165
                criterias.append(Contains('status', applied_filters))
166

  
167
        return criterias
168

  
145 169
    def export_to_xml(self, charset=None):
146 170
        root = ET.Element(self.xml_root_node)
147 171
        fields = [
wcs/qommon/templatetags/qommon.py
605 605
def objects(forms_source, slug):
606 606
    if hasattr(slug, 'get_value'):
607 607
        slug = slug.get_value()  # unlazy
608
    # assume formdef_source is an instance of CardsSouce of FormsSource
608
    # assume formdef_source is an instance of CardsSource of FormsSource
609 609
    return getattr(forms_source, slug).objects
610 610

  
611 611

  
612
@register.filter
613
def with_custom_view(queryset, custom_view_slug):
614
    return queryset.with_custom_view(custom_view_slug)
615

  
616

  
612 617
@register.filter
613 618
def order_by(queryset, attribute):
614 619
    if hasattr(attribute, 'get_value'):
wcs/variables.py
91 91
                break
92 92
        return self._clone(self._criterias + [Equal('status', wf_status)])
93 93

  
94
    def with_custom_view(self, custom_view_slug):
95
        lookup_criterias = [
96
            Equal('formdef_type', self._formdef.xml_root_node),
97
            Equal('formdef_id', self._formdef.id),
98
            NotEqual('visibility', 'owner'),
99
            Equal('slug', custom_view_slug),
100
        ]
101
        try:
102
            custom_view = get_publisher().custom_view_class.select(lookup_criterias)[0]
103
        except IndexError:
104
            return self._clone([Equal('status', '_none')])
105
        return self._clone(self._criterias + custom_view.get_criterias(), order_by=custom_view.order_by)
106

  
94 107
    def exclude_self(self):
95 108
        assert self._formdata
96 109
        return self._clone(self._criterias + [NotEqual('id', str(self._formdata.id))])
97
-