【问题标题】:Flask Admin Display Enum Value Instead of NameFlask 管理员显示枚举值而不是名称
【发布时间】:2019-06-20 10:58:36
【问题描述】:

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

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:开发人员)在模态和可编辑列选项中显示,但不幸的是,显示仍在使用名称(IE:名称)。

为了澄清,我实质上是在询问是否有任何方式让 Flask Admin 在显示表中显示枚举的值,而不是默认的名称。提前谢谢你...

还提供 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)

【问题讨论】:

    标签: python-2.7 flask flask-sqlalchemy flask-admin


    【解决方案1】:

    如果您要显示多个 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
    
        #  ...
    

    还可以考虑按照SO answer 中的说明设置 AccessLevel 选项。这意味着您不必在模型视图定义中重复枚举名称/值。注意AccessLevel 类中的__str____html__ 方法。

    示例

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

    【讨论】:

      【解决方案2】:

      您需要column_formatters 功能才能在表格中显示正确的值。格式化函数定义如下:

      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,
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-10-03
        • 2022-11-01
        • 2016-01-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多