Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
flask-admin
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
JIRA
JIRA
Merge Requests
0
Merge Requests
0
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Commits
Issue Boards
Open sidebar
Python-Dev
flask-admin
Commits
6c53c78b
Commit
6c53c78b
authored
Apr 11, 2014
by
Bryan Hoyt
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "Merge branch 'named-filter-forms'"
This reverts commit
323405e6
, reversing changes made to
41a68dde
.
parent
4ec6473a
Changes
7
Show whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
152 additions
and
190 deletions
+152
-190
list.html
examples/layout/templates/list.html
+1
-1
base.py
flask_admin/model/base.py
+70
-120
filters.js
flask_admin/static/admin/js/filters.js
+16
-13
layout.html
flask_admin/templates/admin/model/layout.html
+11
-11
list.html
flask_admin/templates/admin/model/list.html
+4
-2
test_basic.py
flask_admin/tests/sqlamodel/test_basic.py
+48
-41
test_model.py
flask_admin/tests/test_model.py
+2
-2
No files found.
examples/layout/templates/list.html
View file @
6c53c78b
flask_admin/model/base.py
View file @
6c53c78b
import
re
import
warnings
from
flask
import
request
,
url_for
,
redirect
,
flash
,
abort
,
json
,
Response
...
...
@@ -19,25 +18,6 @@ from .helpers import prettify_name, get_mdict_item_or_list
from
.ajax
import
AjaxModelLoader
try
:
from
collections
import
OrderedDict
except
ImportError
:
# Bare-bones OrderedDict implementation for Python2.6 compatibility
class
OrderedDict
(
dict
):
def
__init__
(
self
,
*
args
,
**
kwargs
):
dict
.
__init__
(
self
,
*
args
,
**
kwargs
)
self
.
ordered_keys
=
[]
def
__setitem__
(
self
,
key
,
value
):
self
.
ordered_keys
.
append
(
key
)
dict
.
__setitem__
(
self
,
key
,
value
)
def
__iter__
(
self
):
return
(
k
for
k
in
self
.
ordered_keys
)
def
iteritems
(
self
):
return
((
k
,
self
[
k
])
for
k
in
self
.
ordered_keys
)
def
items
(
self
):
return
list
(
self
.
iteritems
())
class
BaseModelView
(
BaseView
,
ActionsMixin
):
"""
Base model view.
...
...
@@ -272,18 +252,6 @@ class BaseModelView(BaseView, ActionsMixin):
column_filters = ('user', 'email')
"""
named_filter_urls
=
False
"""
Set to True to use human-readable names for filters in URL parameters.
False by default so as to be robust across translations.
Changing this parameter will break any existing URLs.
Override unique_filter_label() if you want to change the default format
of filter urls. This parameter only controls the default method.
"""
column_display_pk
=
ObsoleteAttr
(
'column_display_pk'
,
'list_display_pk'
,
False
)
...
...
@@ -576,19 +544,25 @@ class BaseModelView(BaseView, ActionsMixin):
self
.
column_descriptions
=
dict
()
if
self
.
_filters
:
self
.
_flattened_filters_by_group
=
OrderedDict
()
for
flt
in
self
.
_filters
:
if
flt
.
name
not
in
self
.
_flattened_filters_by_group
:
self
.
_flattened_filters_by_group
[
flt
.
name
]
=
[]
group
=
self
.
_flattened_filters_by_group
[
flt
.
name
]
group
.
append
({
'name'
:
flt
.
name
,
'label'
:
self
.
unique_filter_label
(
flt
),
'operation'
:
flt
.
operation
(),
'options'
:
flt
.
get_options
(
self
)
or
None
,
'data_type'
:
flt
.
data_type
})
self
.
_filter_groups
=
[]
self
.
_filter_dict
=
dict
()
for
i
,
n
in
enumerate
(
self
.
_filters
):
if
n
.
name
not
in
self
.
_filter_dict
:
group
=
[]
self
.
_filter_dict
[
n
.
name
]
=
group
self
.
_filter_groups
.
append
((
n
.
name
,
group
))
else
:
group
=
self
.
_filter_dict
[
n
.
name
]
group
.
append
((
i
,
n
.
operation
()))
self
.
_filter_types
=
dict
((
i
,
f
.
data_type
)
for
i
,
f
in
enumerate
(
self
.
_filters
)
if
f
.
data_type
)
else
:
self
.
_flattened_filters_by_group
=
None
self
.
_filter_groups
=
None
self
.
_filter_types
=
None
# Form rendering rules
if
self
.
form_create_rules
:
...
...
@@ -974,82 +948,45 @@ class BaseModelView(BaseView, ActionsMixin):
def
get_empty_list_message
(
self
):
return
gettext
(
'There are no items in the table.'
)
def
unique_filter_label
(
self
,
flt
):
# URL generation helper
def
_get_extra_args
(
self
):
"""
Given a filter `flt`, return a unique name for that filter in
this view.
By default, returns a numeric index or a human-readable filter name
Does not include the `flt[n]_` portion of the filter name.
To use custom names, override this function, eg
def unique_filter_label(self, flt):
return flt.name + flt.__class__.__name__
Be aware that if you override this method, the default URL format
will no longer work.
"""
if
self
.
named_filter_urls
:
return
re
.
sub
(
'
\
W'
,
'_'
,
u'{name}_{operation}'
.
format
(
name
=
flt
.
name
,
operation
=
flt
.
operation
()))
.
lower
()
else
:
return
str
(
self
.
_filters
.
index
(
flt
))
def
get_filter_args
(
self
):
Return arguments from query string.
"""
Retrieve and parse filter parameters from the request URL.
Returns a list of 2-tuples in the format [(idx, value), ...],
where idx is the index into the list returned by get_filters().
Override this method to provide your own URL filter format.
"""
if
not
self
.
_filters
:
return
None
filter_idx_by_label
=
dict
((
self
.
unique_filter_label
(
flt
),
i
)
for
i
,
flt
in
enumerate
(
self
.
_filters
))
page
=
request
.
args
.
get
(
'page'
,
0
,
type
=
int
)
sort
=
request
.
args
.
get
(
'sort'
,
None
,
type
=
int
)
sort_desc
=
request
.
args
.
get
(
'desc'
,
None
,
type
=
int
)
search
=
request
.
args
.
get
(
'search'
,
None
)
# Gather filters
if
self
.
_filters
:
sfilters
=
[]
for
n
in
request
.
args
:
if
not
n
.
startswith
(
'flt'
):
continue
if
'_'
not
in
n
:
if
n
.
startswith
(
'flt'
):
ofs
=
n
.
find
(
'_'
)
if
ofs
==
-
1
:
continue
pos
,
filter_label
=
n
[
3
:]
.
split
(
'_'
,
1
)
# If pos not specified, just add incrementally to the list.
pos
=
int
(
pos
)
if
pos
else
len
(
sfilters
)
try
:
# See if filter is numeric
idx
=
int
(
filter_label
)
pos
=
int
(
n
[
3
:
ofs
])
idx
=
int
(
n
[
ofs
+
1
:]
)
except
ValueError
:
# If non-numeric, look filter up by name
try
:
idx
=
filter_idx_by_label
[
filter_label
]
except
KeyError
:
# No matching filter name
continue
if
0
<=
idx
<
len
(
self
.
_filters
):
if
idx
>=
0
and
idx
<
len
(
self
.
_filters
):
flt
=
self
.
_filters
[
idx
]
value
=
request
.
args
[
n
]
if
flt
.
validate
(
value
):
sfilters
.
append
((
pos
,
(
idx
,
flt
.
clean
(
value
))))
return
[
v
[
1
]
for
v
in
sorted
(
sfilters
,
key
=
lambda
n
:
n
[
0
])]
filters
=
[
v
[
1
]
for
v
in
sorted
(
sfilters
,
key
=
lambda
n
:
n
[
0
])]
else
:
filters
=
None
def
_get_listing_args
(
self
):
"""
Return generic list view arguments from query string.
"""
page
=
request
.
args
.
get
(
'page'
,
0
,
type
=
int
)
sort
=
request
.
args
.
get
(
'sort'
,
None
,
type
=
int
)
sort_desc
=
request
.
args
.
get
(
'desc'
,
None
,
type
=
int
)
search
=
request
.
args
.
get
(
'search'
,
None
)
return
page
,
sort
,
sort_desc
,
search
return
page
,
sort
,
sort_desc
,
search
,
filters
def
_get_url
(
self
,
view
=
None
,
page
=
None
,
sort
=
None
,
sort_desc
=
None
,
search
=
None
,
filters
=
None
):
...
...
@@ -1079,8 +1016,8 @@ class BaseModelView(BaseView, ActionsMixin):
kwargs
=
dict
(
page
=
page
,
sort
=
sort
,
desc
=
sort_desc
,
search
=
search
)
if
filters
:
for
flt
in
filters
:
key
=
'flt
_
%
s'
%
self
.
unique_filter_label
(
self
.
_filters
[
flt
[
0
]
])
for
i
,
flt
in
enumerate
(
filters
)
:
key
=
'flt
%
d_
%
d'
%
(
i
,
flt
[
0
])
kwargs
[
key
]
=
flt
[
1
]
return
url_for
(
view
,
**
kwargs
)
...
...
@@ -1101,11 +1038,11 @@ class BaseModelView(BaseView, ActionsMixin):
"""
return
rec_getattr
(
model
,
name
)
def
filters_by_label
(
self
):
def
_get_filter_dict
(
self
):
"""
Flattened dict of all filters, indexed by their label
.
Return flattened filter dictionary which can be JSON-serialized
.
"""
return
dict
((
self
.
unique_filter_label
(
flt
),
flt
)
for
flt
in
self
.
_filters
)
return
dict
((
as_unicode
(
k
),
v
)
for
k
,
v
in
iteritems
(
self
.
_filter_dict
)
)
@
contextfunction
def
get_list_value
(
self
,
context
,
model
,
name
):
...
...
@@ -1167,8 +1104,7 @@ class BaseModelView(BaseView, ActionsMixin):
List view
"""
# Grab parameters from URL
page
,
sort_idx
,
sort_desc
,
search
=
self
.
_get_listing_args
()
filters
=
self
.
get_filter_args
()
page
,
sort_idx
,
sort_desc
,
search
,
filters
=
self
.
_get_extra_args
()
# Map column index to column name
sort_column
=
self
.
_get_column_by_idx
(
sort_idx
)
...
...
@@ -1184,6 +1120,18 @@ class BaseModelView(BaseView, ActionsMixin):
if
count
%
self
.
page_size
!=
0
:
num_pages
+=
1
# Pregenerate filters
if
self
.
_filters
:
filters_data
=
dict
()
for
idx
,
f
in
enumerate
(
self
.
_filters
):
flt_data
=
f
.
get_options
(
self
)
if
flt_data
:
filters_data
[
idx
]
=
flt_data
else
:
filters_data
=
None
# Various URL generation helpers
def
pager_url
(
p
):
# Do not add page number if it is first page
...
...
@@ -1238,7 +1186,9 @@ class BaseModelView(BaseView, ActionsMixin):
search
=
search
,
# Filters
filters
=
self
.
_filters
,
filter_groups
=
self
.
_flattened_filters_by_group
,
filter_groups
=
self
.
_filter_groups
,
filter_types
=
self
.
_filter_types
,
filter_data
=
filters_data
,
active_filters
=
filters
,
# Actions
...
...
flask_admin/static/admin/js/filters.js
View file @
6c53c78b
var
AdminFilters
=
function
(
element
,
filters_element
,
filters_by_group
)
{
var
AdminFilters
=
function
(
element
,
filters_element
,
operations
,
options
,
types
)
{
var
$root
=
$
(
element
);
var
$container
=
$
(
'.filters'
,
$root
);
var
lastCount
=
0
;
...
...
@@ -23,7 +23,7 @@ var AdminFilters = function(element, filters_element, filters_by_group) {
return
false
;
}
function
addFilter
(
name
,
subfilters
)
{
function
addFilter
(
name
,
op
)
{
var
$el
=
$
(
'<tr />'
).
appendTo
(
$container
);
// Filter list
...
...
@@ -41,8 +41,8 @@ var AdminFilters = function(element, filters_element, filters_by_group) {
var
$select
=
$
(
'<select class="filter-op" />'
)
.
change
(
changeOperation
);
$
(
subfilters
).
each
(
function
()
{
$select
.
append
(
$
(
'<option/>'
).
attr
(
'value'
,
this
.
label
).
text
(
this
.
operation
));
$
(
op
).
each
(
function
()
{
$select
.
append
(
$
(
'<option/>'
).
attr
(
'value'
,
this
[
0
]).
text
(
this
[
1
]
));
});
$el
.
append
(
...
...
@@ -51,14 +51,16 @@ var AdminFilters = function(element, filters_element, filters_by_group) {
$select
.
select2
({
width
:
'resolve'
});
// Input
var
optId
=
op
[
0
][
0
];
var
$field
;
var
firstFilter
=
subfilters
[
0
];
if
(
firstFilter
.
options
)
{
if
(
optId
in
options
)
{
$field
=
$
(
'<select class="filter-val" />'
)
.
attr
(
'name'
,
'flt'
+
lastCount
+
'_'
+
firstFilter
.
label
);
.
attr
(
'name'
,
'flt'
+
lastCount
+
'_'
+
optId
);
$
(
firstFilter
.
options
).
each
(
function
()
{
$
(
options
[
optId
]
).
each
(
function
()
{
$field
.
append
(
$
(
'<option/>'
)
.
val
(
this
[
0
]).
text
(
this
[
1
]));
});
...
...
@@ -68,13 +70,13 @@ var AdminFilters = function(element, filters_element, filters_by_group) {
}
else
{
$field
=
$
(
'<input type="text" class="filter-val" />'
)
.
attr
(
'name'
,
'flt'
+
lastCount
+
'_'
+
firstFilter
.
label
);
.
attr
(
'name'
,
'flt'
+
lastCount
+
'_'
+
optId
);
$el
.
append
(
$
(
'<td/>'
).
append
(
$field
));
}
if
(
firstFilter
.
data_type
)
{
$field
.
attr
(
'data-role'
,
firstFilter
.
data_type
);
faForm
.
applyStyle
(
$field
,
firstFilter
.
data_type
);
if
(
optId
in
types
)
{
$field
.
attr
(
'data-role'
,
types
[
optId
]
);
faForm
.
applyStyle
(
$field
,
types
[
optId
]
);
}
lastCount
+=
1
;
...
...
@@ -82,7 +84,8 @@ var AdminFilters = function(element, filters_element, filters_by_group) {
$
(
'a.filter'
,
filters_element
).
click
(
function
()
{
var
name
=
$
(
this
).
text
().
trim
();
addFilter
(
name
,
filters_by_group
[
name
]);
addFilter
(
name
,
operations
[
name
]);
$
(
'button'
,
$root
).
show
();
...
...
flask_admin/templates/admin/model/layout.html
View file @
6c53c78b
...
...
@@ -5,7 +5,7 @@
<ul
class=
"dropdown-menu field-filters"
>
{% for k in filter_groups %}
<li>
<a
href=
"javascript:void(0)"
class=
"filter"
onclick=
"return false;"
>
{{ k }}
</a>
<a
href=
"javascript:void(0)"
class=
"filter"
onclick=
"return false;"
>
{{ k
[0]
}}
</a>
</li>
{% endfor %}
</ul>
...
...
@@ -23,29 +23,29 @@
<table
class=
"filters"
>
{%- for i, flt in enumerate(active_filters) -%}
<tr>
{% set filter = filters[flt[0]] %}
{%- set filter_label = admin_view.unique_filter_label(filter) -%}
{% set filter = admin_view._filters[flt[0]] %}
<td>
<a
href=
"javascript:void(0)"
class=
"btn remove-filter"
title=
"{{ _gettext('Remove Filter') }}"
>
<span
class=
"close-icon"
>
×
</span>
{{ filter
.name
}}
<span
class=
"close-icon"
>
×
</span>
{{ filter
s[flt[0]]
}}
</a>
</td>
<td>
<select
class=
"filter-op"
data-role=
"select2"
>
{% for
subfilter in filter_groups
[filter.name] %}
<option
value=
"{{
subfilter.label }}"
{%
if
subfilter
.
label =
=
filter_label
%}
selected=
"selected"
{%
endif
%}
>
{{ subfilter.operation
}}
</option>
{% for
op in admin_view._filter_dict
[filter.name] %}
<option
value=
"{{
op[0] }}"
{%
if
flt
[
0
]
==
op
[
0
]
%}
selected=
"selected"
{%
endif
%}
>
{{ op[1]
}}
</option>
{% endfor %}
</select>
</td>
<td>
{%- if filter.options -%}
<select
name=
"flt{{ i }}_{{ filter_label }}"
class=
"filter-val"
data-role=
"select2"
>
{%- for o in filter.options %}
<option
value=
"{{ o[0] }}"
{%
if
flt
[
1
]
==
o
[
0
]
%}
selected
{%
endif
%}
>
{{ o[1] }}
</option>
{%- set data = filter_data.get(flt[0]) -%}
{%- if data -%}
<select
name=
"flt{{ i }}_{{ flt[0] }}"
class=
"filter-val"
data-role=
"select2"
>
{%- for d in data %}
<option
value=
"{{ d[0] }}"
{%
if
flt
[
1
]
==
d
[
0
]
%}
selected
{%
endif
%}
>
{{ d[1] }}
</option>
{%- endfor %}
</select>
{%- else -%}
<input
name=
"flt{{ i }}_{{ f
ilter_label }}"
type=
"text"
value=
"{{ flt[1] or '' }}"
class=
"filter-val"
{%
if
filter
.
data_type
%}
data-role=
"{{ filter.data_type
}}"
{%
endif
%}
></input>
<input
name=
"flt{{ i }}_{{ f
lt[0] }}"
type=
"text"
value=
"{{ flt[1] or '' }}"
class=
"filter-val"
{%
if
flt
[
0
]
in
filter_types
%}
data-role=
"{{ filter_types[flt[0]]
}}"
{%
endif
%}
></input>
{%- endif -%}
</td>
</tr>
...
...
flask_admin/templates/admin/model/list.html
View file @
6c53c78b
...
...
@@ -159,10 +159,12 @@
html
:
true
,
placement
:
'bottom'
});
{
%
if
filter_groups
is
not
none
%
}
{
%
if
filter_groups
is
not
none
and
filter_data
is
not
none
%
}
var
filter
=
new
AdminFilters
(
'#filter_form'
,
'.field-filters'
,
{{
filter_groups
|
tojson
|
safe
}}
{{
admin_view
.
_get_filter_dict
()
|
tojson
|
safe
}},
{{
filter_data
|
tojson
|
safe
}},
{{
filter_types
|
tojson
|
safe
}}
);
{
%
endif
%
}
})(
jQuery
);
...
...
flask_admin/tests/sqlamodel/test_basic.py
View file @
6c53c78b
...
...
@@ -233,52 +233,61 @@ def test_column_filters():
eq_
(
len
(
view
.
_filters
),
4
)
eq_
([
(
f
[
'label'
],
f
[
'operation'
])
for
f
in
view
.
_flattened_filters_by_group
[
'Test1'
]
],
[(
'0'
,
u'equals'
),
(
'1'
,
u'not equal'
),
(
'2'
,
u'contains'
),
(
'3'
,
u'not contains'
)])
eq_
(
view
.
_filter_dict
,
{
u'Test1'
:
[
(
0
,
u'equals'
),
(
1
,
u'not equal'
),
(
2
,
u'contains'
),
(
3
,
u'not contains'
)
]})
# Test filter that references property
view
=
CustomModelView
(
Model2
,
db
.
session
,
column_filters
=
[
'model1'
])
eq_
([
(
f
[
'label'
],
f
[
'operation'
])
for
f
in
view
.
_flattened_filters_by_group
[
'Model1 / Test1'
]
],
[(
'0'
,
u'equals'
),
(
'1'
,
u'not equal'
),
(
'2'
,
u'contains'
),
(
'3'
,
u'not contains'
)])
eq_
([
(
f
[
'label'
],
f
[
'operation'
])
for
f
in
view
.
_flattened_filters_by_group
[
'Model1 / Test2'
]
],
[(
'4'
,
u'equals'
),
(
'5'
,
u'not equal'
),
(
'6'
,
u'contains'
),
(
'7'
,
u'not contains'
)])
eq_
([
(
f
[
'label'
],
f
[
'operation'
])
for
f
in
view
.
_flattened_filters_by_group
[
'Model1 / Test3'
]
],
[(
'8'
,
u'equals'
),
(
'9'
,
u'not equal'
),
(
'10'
,
u'contains'
),
(
'11'
,
u'not contains'
)])
eq_
([
(
f
[
'label'
],
f
[
'operation'
])
for
f
in
view
.
_flattened_filters_by_group
[
'Model1 / Test4'
]
],
[(
'12'
,
u'equals'
),
(
'13'
,
u'not equal'
),
(
'14'
,
u'contains'
),
(
'15'
,
u'not contains'
)])
eq_
([
(
f
[
'label'
],
f
[
'operation'
])
for
f
in
view
.
_flattened_filters_by_group
[
'Model1 / Bool Field'
]
],
[(
'16'
,
u'equals'
),
(
'17'
,
u'not equal'
)])
eq_
([
(
f
[
'label'
],
f
[
'operation'
])
for
f
in
view
.
_flattened_filters_by_group
[
'Model1 / Enum Field'
]
],
[(
'18'
,
u'equals'
),
(
'19'
,
u'not equal'
)])
eq_
(
view
.
_filter_dict
,
{
u'Model1 / Test1'
:
[
(
0
,
u'equals'
),
(
1
,
u'not equal'
),
(
2
,
u'contains'
),
(
3
,
u'not contains'
)
],
'Model1 / Test2'
:
[
(
4
,
'equals'
),
(
5
,
'not equal'
),
(
6
,
'contains'
),
(
7
,
'not contains'
)
],
u'Model1 / Test3'
:
[
(
8
,
u'equals'
),
(
9
,
u'not equal'
),
(
10
,
u'contains'
),
(
11
,
u'not contains'
)
],
u'Model1 / Test4'
:
[
(
12
,
u'equals'
),
(
13
,
u'not equal'
),
(
14
,
u'contains'
),
(
15
,
u'not contains'
)
],
u'Model1 / Bool Field'
:
[
(
16
,
u'equals'
),
(
17
,
u'not equal'
),
],
u'Model1 / Enum Field'
:
[
(
18
,
u'equals'
),
(
19
,
u'not equal'
),
]})
# Test filter with a dot
view
=
CustomModelView
(
Model2
,
db
.
session
,
column_filters
=
[
'model1.bool_field'
])
eq_
([
(
f
[
'label'
],
f
[
'operation'
])
for
f
in
view
.
_flattened_filters_by_group
[
'Model1 / Bool Field'
]
],
[(
'0'
,
u'equals'
),
(
'1'
,
u'not equal'
)])
eq_
(
view
.
_filter_dict
,
{
'Model1 / Bool Field'
:
[
(
0
,
'equals'
),
(
1
,
'not equal'
),
]})
# Fill DB
model1_obj1
=
Model1
(
'model1_obj1'
,
bool_field
=
True
)
...
...
@@ -315,11 +324,9 @@ def test_column_filters():
column_filters
=
[
'int_field'
])
admin
.
add_view
(
view
)
eq_
([
(
f
[
'label'
],
f
[
'operation'
])
for
f
in
view
.
_flattened_filters_by_group
[
'Int Field'
]
],
[(
'0'
,
u'equals'
),
(
'1'
,
u'not equal'
),
(
'2'
,
u'greater than'
),
(
'3'
,
u'smaller than'
)])
eq_
(
view
.
_filter_dict
,
{
'Int Field'
:
[(
0
,
'equals'
),
(
1
,
'not equal'
),
(
2
,
'greater than'
),
(
3
,
'smaller than'
)]})
#Test filters to joined table field
view
=
CustomModelView
(
...
...
flask_admin/tests/test_model.py
View file @
6c53c78b
...
...
@@ -302,8 +302,8 @@ def test_column_filters():
eq_
(
view
.
_filters
[
0
]
.
name
,
'col1'
)
eq_
(
view
.
_filters
[
1
]
.
name
,
'col2'
)
eq_
(
[
(
f
[
'label'
],
f
[
'operation'
])
for
f
in
view
.
_flattened_filters_by_group
[
'col1'
]
],
[(
'0'
,
'test'
)])
eq_
([
(
f
[
'label'
],
f
[
'operation'
])
for
f
in
view
.
_flattened_filters_by_group
[
'col2'
]
],
[(
'1'
,
'test'
)]
)
eq_
(
view
.
_filter_dict
,
{
'col1'
:
[(
0
,
'test'
)],
'col2'
:
[(
1
,
'test'
)]}
)
# TODO: Make calls with filters
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment