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): ...@@ -62,7 +62,10 @@ class PostAdmin(sqlamodel.ModelView):
searchable_columns = ('title', User.username) 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 # Pass arguments to WTForms. In this case, change label for text field to
# be 'Big Text' and add required() validator. # be 'Big Text' and add required() validator.
......
...@@ -146,11 +146,14 @@ class ModelView(BaseModelView): ...@@ -146,11 +146,14 @@ class ModelView(BaseModelView):
self._auto_joins = self.list_select_related self._auto_joins = self.list_select_related
# Internal API # Internal API
def _get_model_iterator(self): def _get_model_iterator(self, model=None):
""" """
Return property iterator for the model 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 # Scaffolding
def scaffold_pk(self): def scaffold_pk(self):
...@@ -269,29 +272,62 @@ class ModelView(BaseModelView): ...@@ -269,29 +272,62 @@ class ModelView(BaseModelView):
name == 'Text' or name == 'UnicodeText') name == 'Text' or name == 'UnicodeText')
def scaffold_filters(self, name): 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: if column.foreign_keys or column.primary_key:
raise Exception('Can not filter more than on one column for %s' % name) 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): type_name = type(column.type).__name__
visible_name = self.get_column_name(name.property.key) 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: 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__ type_name = type(column.type).__name__
flt = self.filter_converter.convert(type_name, flt = self.filter_converter.convert(type_name,
column, column,
visible_name) visible_name)
if flt: if flt:
# If there's relation to other table, do it # If there's relation to other table, do it
if column.table != self.model.__table__: if column.table != self.model.__table__:
self._filter_joins_names.add(column.table.name) self._filter_joins_names.add(column.table.name)
return flt return flt
def is_valid_filter(self, filter): 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