Commit 6a9f6312 authored by Serge S. Koval's avatar Serge S. Koval

Automatic filter scaffolding for models.

parent 2c18d47d
......@@ -62,7 +62,10 @@ class PostAdmin(sqlamodel.ModelView):
searchable_columns = ('title', User.username)
column_filters = (User.username, 'title', 'date', filters.FilterLike(Post.title, 'Fixed Title', options=(('test1', 'Test 1'), ('test2', 'Test 2'))))
column_filters = (User,
'title',
'date',
filters.FilterLike(Post.title, 'Fixed Title', options=(('test1', 'Test 1'), ('test2', 'Test 2'))))
# Pass arguments to WTForms. In this case, change label for text field to
# be 'Big Text' and add required() validator.
......
......@@ -146,11 +146,14 @@ class ModelView(BaseModelView):
self._auto_joins = self.list_select_related
# Internal API
def _get_model_iterator(self):
def _get_model_iterator(self, model=None):
"""
Return property iterator for the model
"""
return self.model._sa_class_manager.mapper.iterate_properties
if model is None:
model = self.model
return model._sa_class_manager.mapper.iterate_properties
# Scaffolding
def scaffold_pk(self):
......@@ -269,29 +272,62 @@ class ModelView(BaseModelView):
name == 'Text' or name == 'UnicodeText')
def scaffold_filters(self, name):
columns = self._get_columns_for_field(name)
if isinstance(name, basestring):
attr = getattr(self.model, name, None)
else:
attr = name
if attr is None:
raise Exception('Failed to find field for filter: %s' % name)
if hasattr(attr, '_sa_class_manager'):
filters = []
for p in self._get_model_iterator(attr):
if hasattr(p, 'columns'):
# TODO: Check for multiple columns
column = p.columns[0]
if len(columns) > 1:
raise Exception('Can not filter more than on one column for %s' % name)
if column.foreign_keys or column.primary_key:
continue
column = columns[0]
visible_name = '%s / %s' % (self.get_column_name(attr.__table__.name),
self.get_column_name(p.key))
if not isinstance(name, basestring):
visible_name = self.get_column_name(name.property.key)
type_name = type(column.type).__name__
flt = self.filter_converter.convert(type_name,
column,
visible_name)
if flt:
self._filter_joins_names.add(column.table.name)
filters.extend(flt)
return filters
else:
visible_name = self.get_column_name(name)
columns = self._get_columns_for_field(attr)
if len(columns) > 1:
raise Exception('Can not filter more than on one column for %s' % name)
column = columns[0]
if not isinstance(name, basestring):
visible_name = self.get_column_name(name.property.key)
else:
visible_name = self.get_column_name(name)
type_name = type(column.type).__name__
flt = self.filter_converter.convert(type_name,
column,
visible_name)
type_name = type(column.type).__name__
flt = self.filter_converter.convert(type_name,
column,
visible_name)
if flt:
# If there's relation to other table, do it
if column.table != self.model.__table__:
self._filter_joins_names.add(column.table.name)
if flt:
# If there's relation to other table, do it
if column.table != self.model.__table__:
self._filter_joins_names.add(column.table.name)
return flt
return flt
def is_valid_filter(self, filter):
"""
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment