Skip to content

Commit

Permalink
Adds a new macro to allow getting filter values easily (apache#5547)
Browse files Browse the repository at this point in the history
* Adds new macro to get filter values from "filters" and "extra_filters"

Adds test for filter_values macro

Adds doco for filter_values

Changes filter_values return type to be a list rather than string

* Makes return value type consistent
- filter_values always return a list
  • Loading branch information
mjsilva authored and mistercrunch committed Sep 17, 2018
1 parent 0e93a94 commit 041fe52
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 1 deletion.
2 changes: 2 additions & 0 deletions docs/sqllab.rst
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ Superset's Jinja context:

.. autofunction:: superset.jinja_context.url_param

.. autofunction:: superset.jinja_context.filter_values

Extending macros
''''''''''''''''

Expand Down
45 changes: 44 additions & 1 deletion superset/jinja_context.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,50 @@ def current_username():
return g.user.username


class BaseTemplateProcessor(object):
def filter_values(column, default=None):
""" Gets a values for a particular filter as a list
This is useful if:
- you want to use a filter box to filter a query where the name of filter box
column doesn't match the one in the select statement
- you want to have the ability for filter inside the main query for speed purposes
This searches for "filters" and "extra_filters" in form_data for a match
Usage example:
* SELECT action, count(*) as times
FROM logs
WHERE action in ( {{ "'" + "','".join(filter_values('action_type')) + "'" )
GROUP BY 1
:param column: column/filter name to lookup
:type column: str
:param default: default value to return if there's no matching columns
:type default: str
:return: returns a list of filter values
:rtype: list
"""
form_data = json.loads(request.form.get('form_data', '{}'))
return_val = []
for filter_type in ['filters', 'extra_filters']:
if filter_type not in form_data:
continue

for f in form_data[filter_type]:
if f['col'] == column:
for v in f['val']:
return_val.append(v)

if return_val:
return return_val

if default:
return [default]
else:
return []


class BaseTemplateProcessor(object):
"""Base class for database-specific jinja context
There's this bit of magic in ``process_template`` that instantiates only
Expand Down Expand Up @@ -90,6 +132,7 @@ def __init__(self, database=None, query=None, table=None, **kwargs):
'url_param': url_param,
'current_user_id': current_user_id,
'current_username': current_username,
'filter_values': filter_values,
'form_data': {},
}
self.context.update(kwargs)
Expand Down
65 changes: 65 additions & 0 deletions tests/macro_tests.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals

from flask import json
from tests.base_tests import SupersetTestCase

from superset import app
from superset import jinja_context


class MacroTestCase(SupersetTestCase):

def test_filter_values_macro(self):
form_data1 = {
'extra_filters': [
{'col': 'my_special_filter', 'op': 'in', 'val': ['foo']},
],
'filters': [
{'col': 'my_special_filter2', 'op': 'in', 'val': ['bar']},
],
}

form_data2 = {
'extra_filters': [
{'col': 'my_special_filter', 'op': 'in', 'val': ['foo', 'bar']},
],
}

form_data3 = {
'extra_filters': [
{'col': 'my_special_filter', 'op': 'in', 'val': ['foo', 'bar']},
],
'filters': [
{'col': 'my_special_filter', 'op': 'in', 'val': ['savage']},
],
}

data1 = {'form_data': json.dumps(form_data1)}
data2 = {'form_data': json.dumps(form_data2)}
data3 = {'form_data': json.dumps(form_data3)}

with app.test_request_context(data=data1):
filter_values = jinja_context.filter_values('my_special_filter')
self.assertEqual(filter_values, ['foo'])

filter_values = jinja_context.filter_values('my_special_filter2')
self.assertEqual(filter_values, ['bar'])

filter_values = jinja_context.filter_values('')
self.assertEqual(filter_values, [])

with app.test_request_context(data=data2):
filter_values = jinja_context.filter_values('my_special_filter')
self.assertEqual(filter_values, ['foo', 'bar'])

with app.test_request_context(data=data3):
filter_values = jinja_context.filter_values('my_special_filter')
self.assertEqual(filter_values, ['savage', 'foo', 'bar'])

with app.test_request_context():
filter_values = jinja_context.filter_values('nonexistent_filter', 'foo')
self.assertEqual(filter_values, ['foo'])

0 comments on commit 041fe52

Please sign in to comment.