general: add filtering methods to lazy querysets (#43328)
This commit is contained in:
parent
981528a0e6
commit
7087f4a061
|
@ -883,6 +883,57 @@ def test_lazy_formdata_queryset_distance(pub, variable_test_data):
|
|||
assert len(nearby) == 0
|
||||
|
||||
|
||||
def test_lazy_formdata_queryset_filter(pub, variable_test_data):
|
||||
lazy_formdata = variable_test_data
|
||||
formdef = lazy_formdata._formdef
|
||||
formdef.store()
|
||||
data_class = lazy_formdata._formdef.data_class()
|
||||
for i in range(6):
|
||||
formdata = data_class()
|
||||
formdata.data = {'0': 'bar'}
|
||||
formdata.just_created()
|
||||
formdata.store()
|
||||
for i in range(4):
|
||||
formdata = data_class()
|
||||
formdata.data = {'0': 'foo'}
|
||||
formdata.just_created()
|
||||
formdata.jump_status('finished')
|
||||
formdata.store()
|
||||
|
||||
formdata = data_class()
|
||||
formdata.data = {'0': 'bar'}
|
||||
formdata.status = 'draft'
|
||||
formdata.store()
|
||||
|
||||
# filter function
|
||||
queryset = lazy_formdata.objects.filter_by('foo_foo').apply_filter_value('bar')
|
||||
assert queryset.count == 7
|
||||
queryset = lazy_formdata.objects.filter_by('foo_foo').apply_filter_value('foo')
|
||||
assert queryset.count == 4
|
||||
queryset = lazy_formdata.objects.filter_by('foo_foo').apply_filter_value('X')
|
||||
assert queryset.count == 0
|
||||
|
||||
# filter using attribute name
|
||||
queryset = lazy_formdata.objects.filter_by_foo_foo().apply_filter_value('bar')
|
||||
assert queryset.count == 7
|
||||
|
||||
# filter + exclude current formdata
|
||||
queryset = lazy_formdata.objects.exclude_self().filter_by('foo_foo').apply_filter_value('bar')
|
||||
assert queryset.count == 6
|
||||
|
||||
queryset = lazy_formdata.objects.exclude_self().filter_by('foo_foo').apply_filter_value('foo')
|
||||
assert queryset.count == 4
|
||||
|
||||
# template tags
|
||||
context = pub.substitutions.get_context_variables(mode='lazy')
|
||||
tmpl = Template('{{form_objects|filter_by:"foo_foo"|filter_value:"bar"|count}}')
|
||||
assert tmpl.render(context) == '7'
|
||||
|
||||
pub.substitutions.feed(formdata)
|
||||
tmpl = Template('{{form_objects|filter_by:"foo_foo"|filter_value:form_var_foo_foo|count}}')
|
||||
assert tmpl.render(context) == '7'
|
||||
|
||||
|
||||
def test_lazy_variables(pub, variable_test_data):
|
||||
formdata = FormDef.select()[0].data_class().select()[0]
|
||||
for mode in (None, 'lazy'):
|
||||
|
|
|
@ -518,9 +518,30 @@ def distance_filter(queryset, distance=1000):
|
|||
|
||||
@register.filter
|
||||
def order_by(queryset, attribute):
|
||||
if hasattr(attribute, 'get_value'):
|
||||
attribute = attribute.get_value() # unlazy
|
||||
return queryset.order_by(attribute)
|
||||
|
||||
|
||||
@register.filter
|
||||
def filter_by(queryset, attribute):
|
||||
if hasattr(attribute, 'get_value'):
|
||||
attribute = attribute.get_value() # unlazy
|
||||
return queryset.filter_by(attribute)
|
||||
|
||||
|
||||
@register.filter
|
||||
def filter_value(queryset, value):
|
||||
if hasattr(value, 'get_value'):
|
||||
value = value.get_value() # unlazy
|
||||
return queryset.apply_filter_value(value)
|
||||
|
||||
|
||||
@register.filter
|
||||
def count(queryset):
|
||||
return queryset.count
|
||||
|
||||
|
||||
@register.filter
|
||||
def reproj(coords, projection_name):
|
||||
proj = pyproj.Proj(init='EPSG:4326')
|
||||
|
|
|
@ -74,6 +74,10 @@ class LazyFormDefObjectsManager(object):
|
|||
user = get_request().user
|
||||
return self._clone(self._criterias + [Equal('user_id', str(user.id) if user else '-1')])
|
||||
|
||||
def exclude_self(self):
|
||||
assert self._formdata
|
||||
return self._clone(self._criterias + [NotEqual('id', str(self._formdata.id))])
|
||||
|
||||
def drafts(self):
|
||||
criterias = [x for x in self._criterias if not getattr(x, 'exclude_drafts', False)]
|
||||
return self._clone(criterias + [Equal('status', 'draft')])
|
||||
|
@ -97,12 +101,31 @@ class LazyFormDefObjectsManager(object):
|
|||
return bool(obj._distance < distance)
|
||||
return self._clone(self._criterias + [distance_check])
|
||||
|
||||
def filter_by(self, attribute):
|
||||
qs = self._clone(self._criterias)
|
||||
qs.pending_attr = attribute
|
||||
return qs
|
||||
|
||||
def apply_filter_value(self, value):
|
||||
assert self.pending_attr
|
||||
for field in self._formdef.fields:
|
||||
if getattr(field, 'varname', None) == self.pending_attr:
|
||||
from wcs import sql
|
||||
criteria = Equal(sql.get_field_id(field), value)
|
||||
break
|
||||
else:
|
||||
raise Exception('invalid filter')
|
||||
return self._clone(self._criterias + [criteria])
|
||||
|
||||
def __getattr__(self, attribute):
|
||||
# backward compatibility
|
||||
if attribute.startswith('count_status_'):
|
||||
# backward compatibility
|
||||
status = attribute[len('count_status_'):]
|
||||
return len(self._formdef.data_class().get_ids_with_indexed_value(
|
||||
'status', 'wf-%s' % status))
|
||||
if attribute.startswith('filter_by_'):
|
||||
attribute_name = attribute[len('filter_by_'):]
|
||||
return lambda: self.filter_by(attribute_name)
|
||||
if attribute == 'formdef':
|
||||
warnings.warn('Deprecated access to formdef', DeprecationWarning)
|
||||
return self._formdef
|
||||
|
@ -421,6 +444,10 @@ class LazyFormData(LazyFormDef):
|
|||
# this gets used to generate an email attachment :/
|
||||
return self._formdata.export_to_json(include_files=include_files)
|
||||
|
||||
def get(self, key):
|
||||
# compatibility with |get filter, to return a field by varname
|
||||
return getattr(self.var, key, None)
|
||||
|
||||
def __getitem__(self, key):
|
||||
try:
|
||||
return getattr(self, key)
|
||||
|
|
Loading…
Reference in New Issue