Python 2.7 Flask Admin显示枚举值而不是名称

Python 2.7 Flask Admin显示枚举值而不是名称,python-2.7,flask,flask-sqlalchemy,flask-admin,Python 2.7,Flask,Flask Sqlalchemy,Flask Admin,我有一个使用枚举定义访问级别的模型,如下所示: 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): col

我有一个使用枚举定义访问级别的模型,如下所示:

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属性,我能够以值形式(IE:Developer)在模态和可编辑列选项中显示,但不幸的是,显示仍然使用名称(IE:name)

为了澄清这一点,我本质上是在询问是否有必要让Flask Admin在显示表中显示枚举的值,而不是默认的名称。提前谢谢你

同时提供员工模型,以防有帮助

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)
您需要在表中显示正确值的功能。格式化程序函数的定义如下:

def access_level_formatter(view, context, model, name):
    db_value = getattr(model, name)
    enum_value = getattr(AccessLevel, db_value)
    return enum_value.value
您需要在视图类中指定此格式化程序,它用于
access
列:

class DevelStaffModelView(DevelModelView):
    column_formatters = {
        'access': access_level_formatter,
    }

如果要显示多个
enum
类型,而不是创建单个
column\u格式化程序
,则可以更新Flask管理员使用的

示例

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

    #  ...
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),
    }

    # ...

也应考虑设置Access级别的选择,如本文中所描述的。这意味着您不必在模型视图定义中重复枚举名称/值。请注意

AccessLevel
类中的
\uuuuu str\uuuuuuuuuuuuuuuuuuuuuuuuu
方法

示例

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

    #  ...
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),
    }

    # ...