Projet

Général

Profil

0001-general-add-filtering-methods-to-lazy-querysets-4332.patch

Frédéric Péters, 28 juin 2020 14:44

Télécharger (5,71 ko)

Voir les différences:

Subject: [PATCH 1/2] general: add filtering methods to lazy querysets (#43328)

 tests/test_formdata.py            | 47 +++++++++++++++++++++++++++++++
 wcs/qommon/templatetags/qommon.py | 15 ++++++++++
 wcs/variables.py                  | 29 ++++++++++++++++++-
 3 files changed, 90 insertions(+), 1 deletion(-)
tests/test_formdata.py
882 882
    assert len(nearby) == 0
883 883

  
884 884

  
885
def test_lazy_formdata_queryset_filter(pub, variable_test_data):
886
    lazy_formdata = variable_test_data
887
    formdef = lazy_formdata._formdef
888
    formdef.store()
889
    data_class = lazy_formdata._formdef.data_class()
890
    for i in range(6):
891
        formdata = data_class()
892
        formdata.data = {'0': 'bar'}
893
        formdata.just_created()
894
        formdata.store()
895
    for i in range(4):
896
        formdata = data_class()
897
        formdata.data = {'0': 'foo'}
898
        formdata.just_created()
899
        formdata.jump_status('finished')
900
        formdata.store()
901

  
902
    formdata = data_class()
903
    formdata.data = {'0': 'bar'}
904
    formdata.status = 'draft'
905
    formdata.store()
906

  
907
    # filter function
908
    queryset = lazy_formdata.objects.filter_by('foo_foo').apply_filter_value('bar')
909
    assert queryset.count == 7
910
    queryset = lazy_formdata.objects.filter_by('foo_foo').apply_filter_value('foo')
911
    assert queryset.count == 4
912
    queryset = lazy_formdata.objects.filter_by('foo_foo').apply_filter_value('X')
913
    assert queryset.count == 0
914

  
915
    # filter using attribute name
916
    queryset = lazy_formdata.objects.filter_by_foo_foo().apply_filter_value('bar')
917
    assert queryset.count == 7
918

  
919
    # filter + exclude current formdata
920
    queryset = lazy_formdata.objects.exclude_self().filter_by('foo_foo').apply_filter_value('bar')
921
    assert queryset.count == 6
922

  
923
    queryset = lazy_formdata.objects.exclude_self().filter_by('foo_foo').apply_filter_value('foo')
924
    assert queryset.count == 4
925

  
926
    # template tags
927
    context = pub.substitutions.get_context_variables(mode='lazy')
928
    tmpl = Template('{{form_objects|filter_by:"foo_foo"|filter_value:"bar"|count}}')
929
    assert tmpl.render(context) == '7'
930

  
931

  
885 932
def test_lazy_variables(pub, variable_test_data):
886 933
    formdata = FormDef.select()[0].data_class().select()[0]
887 934
    for mode in (None, 'lazy'):
wcs/qommon/templatetags/qommon.py
460 460
    return queryset.order_by(attribute)
461 461

  
462 462

  
463
@register.filter
464
def filter_by(queryset, attribute):
465
    return queryset.filter_by(attribute)
466

  
467

  
468
@register.filter
469
def filter_value(queryset, value):
470
    return queryset.apply_filter_value(value)
471

  
472

  
473
@register.filter
474
def count(queryset):
475
    return queryset.count
476

  
477

  
463 478
@register.filter
464 479
def reproj(coords, projection_name):
465 480
    proj = pyproj.Proj(init='EPSG:4326')
wcs/variables.py
74 74
        user = get_request().user
75 75
        return self._clone(self._criterias + [Equal('user_id', str(user.id) if user else '-1')])
76 76

  
77
    def exclude_self(self):
78
        assert self._formdata
79
        return self._clone(self._criterias + [NotEqual('id', str(self._formdata.id))])
80

  
77 81
    def drafts(self):
78 82
        criterias = [x for x in self._criterias if not getattr(x, 'exclude_drafts', False)]
79 83
        return self._clone(criterias + [Equal('status', 'draft')])
......
97 101
            return bool(obj._distance < distance)
98 102
        return self._clone(self._criterias + [distance_check])
99 103

  
104
    def filter_by(self, attribute):
105
        qs = self._clone(self._criterias)
106
        qs.pending_attr = attribute
107
        return qs
108

  
109
    def apply_filter_value(self, value):
110
        assert self.pending_attr
111
        for field in self._formdef.fields:
112
            if getattr(field, 'varname', None) == self.pending_attr:
113
                from wcs import sql
114
                criteria = Equal(sql.get_field_id(field), value)
115
                break
116
        else:
117
            raise Exception('invalid filter')
118
        return self._clone(self._criterias + [criteria])
119

  
100 120
    def __getattr__(self, attribute):
101
        # backward compatibility
102 121
        if attribute.startswith('count_status_'):
122
            # backward compatibility
103 123
            status = attribute[len('count_status_'):]
104 124
            return len(self._formdef.data_class().get_ids_with_indexed_value(
105 125
                'status', 'wf-%s' % status))
126
        if attribute.startswith('filter_by_'):
127
            attribute_name = attribute[len('filter_by_'):]
128
            return lambda: self.filter_by(attribute_name)
106 129
        if attribute == 'formdef':
107 130
            warnings.warn('Deprecated access to formdef', DeprecationWarning)
108 131
            return self._formdef
......
421 444
        # this gets used to generate an email attachment :/
422 445
        return self._formdata.export_to_json(include_files=include_files)
423 446

  
447
    def get(self, key):
448
        # compatibility with |get filter, to return a field by varname
449
        return getattr(self.var, key, None)
450

  
424 451
    def __getitem__(self, key):
425 452
        try:
426 453
            return getattr(self, key)
427
-