Commit 49e3dea4 authored by Serge S. Koval's avatar Serge S. Koval

Pass view to the column/type formatting functions

parent 93d94683
...@@ -123,29 +123,11 @@ class ModelView(BaseModelView): ...@@ -123,29 +123,11 @@ class ModelView(BaseModelView):
def scaffold_form(self): def scaffold_form(self):
raise NotImplemented() raise NotImplemented()
@contextfunction def _get_field_value(self, model, name):
def get_list_value(self, context, model, name):
""" """
Returns value to be displayed in list view Get unformatted field value from the model
:param context:
:py:class:`jinja2.runtime.Context`
:param model:
Model instance
:param name:
Field name
""" """
column_fmt = self.column_formatters.get(name) return model.get(name)
if column_fmt is not None:
return column_fmt(context, model, name)
value = model.get(name)
type_fmt = self.column_type_formatters.get(type(value))
if type_fmt is not None:
value = type_fmt(value)
return value
def get_list(self, page, sort_column, sort_desc, search, filters, def get_list(self, page, sort_column, sort_desc, search, filters,
execute=True): execute=True):
......
import warnings
from flask import request, url_for, redirect, flash from flask import request, url_for, redirect, flash
from jinja2 import contextfunction from jinja2 import contextfunction
...@@ -79,14 +81,15 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -79,14 +81,15 @@ class BaseModelView(BaseView, ActionsMixin):
two, you can do something like this:: two, you can do something like this::
class MyModelView(BaseModelView): class MyModelView(BaseModelView):
column_formatters = dict(price=lambda c, m, p: m.price*2) column_formatters = dict(price=lambda v, c, m, p: m.price*2)
The Callback function has the prototype:: The Callback function has the prototype::
def formatter(context, model, name): def formatter(view, context, model, name):
# context is instance of jinja2.runtime.Context # `view` is current administrative view
# model is model instance # `context` is instance of jinja2.runtime.Context
# name is property name # `model` is model instance
# `name` is property name
pass pass
""" """
...@@ -117,6 +120,13 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -117,6 +120,13 @@ class BaseModelView(BaseView, ActionsMixin):
column_type_formatters = MY_DEFAULT_FORMATTERS column_type_formatters = MY_DEFAULT_FORMATTERS
Type formatters have lower priority than list column formatters. Type formatters have lower priority than list column formatters.
The callback function has following prototype::
def type_formatter(view, value):
# `view` is current administrative view
# `value` value to format
pass
""" """
column_labels = ObsoleteAttr('column_labels', 'rename_columns', None) column_labels = ObsoleteAttr('column_labels', 'rename_columns', None)
...@@ -841,6 +851,12 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -841,6 +851,12 @@ class BaseModelView(BaseView, ActionsMixin):
""" """
return name not in self.action_disallowed_list return name not in self.action_disallowed_list
def _get_field_value(self, model, name):
"""
Get unformatted field value from the model
"""
return rec_getattr(model, name)
@contextfunction @contextfunction
def get_list_value(self, context, model, name): def get_list_value(self, context, model, name):
""" """
...@@ -855,9 +871,17 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -855,9 +871,17 @@ class BaseModelView(BaseView, ActionsMixin):
""" """
column_fmt = self.column_formatters.get(name) column_fmt = self.column_formatters.get(name)
if column_fmt is not None: if column_fmt is not None:
return column_fmt(context, model, name) try:
return column_fmt(self, context, model, name)
except TypeError:
warnings.warn('Column formatter prototype was changed to accept view as first input parameter.\n' +
'Please update %s %s formatter to accept 4 parameters.' % (self.name, name),
stacklevel=2)
self.column_formatters[name] = lambda _, c, m, n: column_fmt(c, m, n)
return column_fmt(context, model, name)
value = rec_getattr(model, name) value = self._get_field_value(model, name)
choices_map = self._column_choices_map.get(name, {}) choices_map = self._column_choices_map.get(name, {})
if choices_map: if choices_map:
...@@ -865,7 +889,15 @@ class BaseModelView(BaseView, ActionsMixin): ...@@ -865,7 +889,15 @@ class BaseModelView(BaseView, ActionsMixin):
type_fmt = self.column_type_formatters.get(type(value)) type_fmt = self.column_type_formatters.get(type(value))
if type_fmt is not None: if type_fmt is not None:
value = type_fmt(value) try:
value = type_fmt(self, value)
except TypeError:
warnings.warn('Type formatter prototype was changed to accept view as first input parameter.\n' +
'Please update %s %s formatter to accept 2 parameters.' % (self.name, type(value)),
stacklevel=2)
self.column_type_formatters[type(value)] = lambda _, value: type_fmt(value)
value = type_fmt(value)
return value return value
......
from jinja2 import Markup from jinja2 import Markup
def null_formatter(value): def null_formatter(view, value):
""" """
Return `NULL` as the string for `None` value Return `NULL` as the string for `None` value
...@@ -11,7 +11,7 @@ def null_formatter(value): ...@@ -11,7 +11,7 @@ def null_formatter(value):
return Markup('<i>NULL</i>') return Markup('<i>NULL</i>')
def empty_formatter(value): def empty_formatter(view, value):
""" """
Return empty string for `None` value Return empty string for `None` value
...@@ -21,7 +21,7 @@ def empty_formatter(value): ...@@ -21,7 +21,7 @@ def empty_formatter(value):
return '' return ''
def bool_formatter(value): def bool_formatter(view, value):
""" """
Return check icon if value is `True` or empty string otherwise. Return check icon if value is `True` or empty string otherwise.
...@@ -31,7 +31,7 @@ def bool_formatter(value): ...@@ -31,7 +31,7 @@ def bool_formatter(value):
return Markup('<i class="icon-ok"></i>' if value else '') return Markup('<i class="icon-ok"></i>' if value else '')
def list_formatter(values): def list_formatter(view, values):
""" """
Return string with comma separated values Return string with comma separated values
......
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