Flask Admin 显示枚举值而不是名称
Flask Admin Display Enum Value Instead of Name
我有一个使用枚举来定义访问级别的模型,如下所示:
class DevelModelView(ModelView):
edit_modal = True
def is_accessible(self):
return current_user.is_authenticated and current_user.access is AccessLevel.DEVEL
class DevelStaffModelView(DevelModelView):
column_editable_list = ['access']
column_filters = ['access']
column_searchable_list = ['login', 'email']
form_choices = {'access': [(AccessLevel.DEVEL.name, AccessLevel.DEVEL.value),
(AccessLevel.ADMIN.name, AccessLevel.ADMIN.value),
(AccessLevel.STAFF.name, AccessLevel.STAFF.value)]}
枚举定义如下...
class AccessLevel(Enum):
DEVEL = 'Developer'
ADMIN = 'Administrator'
STAFF = 'Staff Member'
使用 form_choices 属性,我能够在值形式的模式和 editable 列选项中显示(IE:Developer)但不幸的是,显示仍在使用名称(即:姓名)。
为了澄清,我实际上是在问是否有 Flask Admin 显示枚举值而不是默认显示的名称 table。提前谢谢你...
还提供 Staff 模型以防万一它有帮助...
class Staff(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
login = db.Column(db.String(64), unique=True)
_password = db.Column(db.String(128))
email = db.Column(db.String(100))
access = db.Column('access', db.Enum(AccessLevel))
@hybrid_property
def password(self):
return self._password
@password.setter
def password(self, plaintext):
self._password = bcrypt.generate_password_hash(plaintext)
def check_password(self, plaintext):
return bcrypt.check_password_hash(self._password, plaintext)
def __str__(self):
return "%s: %s (%s)" % (self.access.name, self.login, self.email)
您需要 column_formatters 功能才能在 table 中显示正确的值。格式化函数定义如下:
def access_level_formatter(view, context, model, name):
db_value = getattr(model, name)
enum_value = getattr(AccessLevel, db_value)
return enum_value.value
并且您需要在视图 class 中指定此格式化程序,它用于 access
列:
class DevelStaffModelView(DevelModelView):
column_formatters = {
'access': access_level_formatter,
}
如果您有多个 enum
类型要显示,而不是单独创建 column_formatters
,您可以更新 Flask-Admin 使用的 column_type_formatters。
例子
from flask_admin.model import typefmt
class AccessLevel(Enum):
DEVEL = 'Developer'
ADMIN = 'Administrator'
STAFF = 'Staff Member'
# ...
MY_DEFAULT_FORMATTERS = dict(typefmt.BASE_FORMATTERS)
MY_DEFAULT_FORMATTERS.update({
AccessLevel: lambda view, access_level_enum: access_level_enum.value # could use a function here
})
class DevelModelView(ModelView):
column_type_formatters = MY_DEFAULT_FORMATTERS
# ...
还请考虑按照 中所述设置访问级别选项。这意味着您不必在模型视图定义中重复枚举 name/values。注意 __str__
和 __html__
方法在 AccessLevel
class.
例子
from flask_admin.model import typefmt
from wtforms import SelectField
class AccessLevel(Enum):
DEVEL = 'Developer'
ADMIN = 'Administrator'
STAFF = 'Staff Member'
def __str__(self):
return self.name # value string
def __html__(self):
return self.value # option labels
def enum_field_options(enum):
"""Produce WTForm Field instance configuration options for an Enum
Returns a dictionary with 'choices' and 'coerce' keys, use this as
**enum_fields_options(EnumClass) when constructing a field:
enum_selection = SelectField("Enum Selection", **enum_field_options(EnumClass))
Labels are produced from enum_instance.__html__() or
str(eum_instance), value strings with str(enum_instance).
"""
assert not {'__str__', '__html__'}.isdisjoint(vars(enum)), (
"The {!r} enum class does not implement a __str__ or __html__ method")
def coerce(name):
if isinstance(name, enum):
# already coerced to instance of this enum
return name
try:
return enum[name]
except KeyError:
raise ValueError(name)
return dict(choices=[(v, v) for v in enum], coerce=coerce)
class DevelModelView(ModelView):
column_type_formatters = MY_DEFAULT_FORMATTERS
# ...
form_overrides = {
'access': SelectField,
}
form_args = {
'access': enum_field_options(AccessLevel),
}
# ...
我有一个使用枚举来定义访问级别的模型,如下所示:
class DevelModelView(ModelView):
edit_modal = True
def is_accessible(self):
return current_user.is_authenticated and current_user.access is AccessLevel.DEVEL
class DevelStaffModelView(DevelModelView):
column_editable_list = ['access']
column_filters = ['access']
column_searchable_list = ['login', 'email']
form_choices = {'access': [(AccessLevel.DEVEL.name, AccessLevel.DEVEL.value),
(AccessLevel.ADMIN.name, AccessLevel.ADMIN.value),
(AccessLevel.STAFF.name, AccessLevel.STAFF.value)]}
枚举定义如下...
class AccessLevel(Enum):
DEVEL = 'Developer'
ADMIN = 'Administrator'
STAFF = 'Staff Member'
使用 form_choices 属性,我能够在值形式的模式和 editable 列选项中显示(IE:Developer)但不幸的是,显示仍在使用名称(即:姓名)。
为了澄清,我实际上是在问是否有 Flask Admin 显示枚举值而不是默认显示的名称 table。提前谢谢你...
还提供 Staff 模型以防万一它有帮助...
class Staff(db.Model, UserMixin):
id = db.Column(db.Integer, primary_key=True, autoincrement=True)
login = db.Column(db.String(64), unique=True)
_password = db.Column(db.String(128))
email = db.Column(db.String(100))
access = db.Column('access', db.Enum(AccessLevel))
@hybrid_property
def password(self):
return self._password
@password.setter
def password(self, plaintext):
self._password = bcrypt.generate_password_hash(plaintext)
def check_password(self, plaintext):
return bcrypt.check_password_hash(self._password, plaintext)
def __str__(self):
return "%s: %s (%s)" % (self.access.name, self.login, self.email)
您需要 column_formatters 功能才能在 table 中显示正确的值。格式化函数定义如下:
def access_level_formatter(view, context, model, name):
db_value = getattr(model, name)
enum_value = getattr(AccessLevel, db_value)
return enum_value.value
并且您需要在视图 class 中指定此格式化程序,它用于 access
列:
class DevelStaffModelView(DevelModelView):
column_formatters = {
'access': access_level_formatter,
}
如果您有多个 enum
类型要显示,而不是单独创建 column_formatters
,您可以更新 Flask-Admin 使用的 column_type_formatters。
例子
from flask_admin.model import typefmt
class AccessLevel(Enum):
DEVEL = 'Developer'
ADMIN = 'Administrator'
STAFF = 'Staff Member'
# ...
MY_DEFAULT_FORMATTERS = dict(typefmt.BASE_FORMATTERS)
MY_DEFAULT_FORMATTERS.update({
AccessLevel: lambda view, access_level_enum: access_level_enum.value # could use a function here
})
class DevelModelView(ModelView):
column_type_formatters = MY_DEFAULT_FORMATTERS
# ...
还请考虑按照 __str__
和 __html__
方法在 AccessLevel
class.
例子
from flask_admin.model import typefmt
from wtforms import SelectField
class AccessLevel(Enum):
DEVEL = 'Developer'
ADMIN = 'Administrator'
STAFF = 'Staff Member'
def __str__(self):
return self.name # value string
def __html__(self):
return self.value # option labels
def enum_field_options(enum):
"""Produce WTForm Field instance configuration options for an Enum
Returns a dictionary with 'choices' and 'coerce' keys, use this as
**enum_fields_options(EnumClass) when constructing a field:
enum_selection = SelectField("Enum Selection", **enum_field_options(EnumClass))
Labels are produced from enum_instance.__html__() or
str(eum_instance), value strings with str(enum_instance).
"""
assert not {'__str__', '__html__'}.isdisjoint(vars(enum)), (
"The {!r} enum class does not implement a __str__ or __html__ method")
def coerce(name):
if isinstance(name, enum):
# already coerced to instance of this enum
return name
try:
return enum[name]
except KeyError:
raise ValueError(name)
return dict(choices=[(v, v) for v in enum], coerce=coerce)
class DevelModelView(ModelView):
column_type_formatters = MY_DEFAULT_FORMATTERS
# ...
form_overrides = {
'access': SelectField,
}
form_args = {
'access': enum_field_options(AccessLevel),
}
# ...