Python Flask WTForm SelectField在验证时使用枚举值“不是有效选择”

时间:2017-04-01 18:56:13

标签: python flask enums wtforms

我的Python Flask应用程序使用内置python Enum支持的WTForms。我正在尝试提交一个表单(POST),其中SelectField由Enum的所有值填充。

当我点击“提交”时,我发现错误,“不是一个有效的选择。”这看起来很奇怪,因为在检查传入表单的值时,表单看起来确实包含了所提供的枚举值列表中的有效选项。

我正在使用名为AJBEnum的枚举的子类,其格式如下:

class UserRole(AJBEnum):
    admin = 0
    recipient = 1

我选择这样做是因为我在项目中使用了许多枚举,并且想要编写一个帮助函数来收集所有选项并将它们格式化为WTForm SelectField元组友好。 AJBEnum的格式如下:

class AJBEnum(Enum):

    @classmethod
    def choices(cls, blank=True):
        choices = []
        if blank == True:
            choices += [("", "")]
        choices += [(choice, choice.desc()) for choice in cls]
        return choices

这意味着我可以在创建SelectField期间为WTForms提供UserRole的所有选择,如下所示:

role = SelectField('Role', choices=UserRole.choices(blank=False), default=UserRole.recipient)

注意函数参数blank提供了一个额外的空白SelectField选项,以防SelectField是可选的。在这种情况下,它不是。

当我点击“提交”按钮时,我会检查路由中的传入请求,并打印form.data我给出了这个内容:

{'email': 'abc@gmail.com', 'password': 'fake', 'plan': 'A', 'confirm': 'fake', 'submit': True, 'id': None, 'role': 'UserRole.recipient'}

正如您所看到的,看来WTForms已经对UserRole.recipient进行了字符串化。有没有办法强制WTForms将传入的POST请求值转换回原来的Enum值?

1 个答案:

答案 0 :(得分:3)

  

有没有办法强制使用WTForms

您正在寻找的参数实际上称为coerce,它接受​​一个可调用的字符串,将该字段的字符串表示形式转换为选择的值。

  1. 选择值应为Enum实例
  2. 字段值应为str(Enum.value)
  3. 字段文字应为Enum.name
  4. 为实现这一目标,我已与Enum名助手合作WTForms

    class FormEnum(Enum):
        @classmethod
        def choices(cls):
            return [(choice, choice.name) for choice in cls]
    
        @classmethod
        def coerce(cls, item):
            return cls(int(item)) if not isinstance(item, cls) else item
    
        def __str__(self):
            return str(self.value)
    

    然后,您可以使用FormEnum编辑SelectField派生值:

    role = SelectField(
            "Role",
            choices = UserRole.choices(),
            coerce = UserRole.coerce)