2017-04-01 55 views
1

我的Python Flask应用程序正在使用带有内置python Enum支持的WTForms。我试图提交一个表单(POST),其中一个SelectField由Enum的所有值填充。Python Flask带有枚举值的WTForm 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': '[email protected]', 'password': 'fake', 'plan': 'A', 'confirm': 'fake', 'submit': True, 'id': None, 'role': 'UserRole.recipient'} 

正如你所看到的,似乎WTForms已字符串化的UserRole。接受者。有没有办法强制WTForms将传入的POST请求值转换回它想要的Enum值?

回答

2

有没有办法强迫WTForms

你要找的实际上是所谓coerce的说法,它接受该字段的字符串表示转换为选择的值调用。

  1. 选择值应该是Enum实例
  2. 字段值应为str(Enum.value)
  3. 现场文字应Enum.name

要做到这一点,我已经扩展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) 

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

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