验证后具有Enum值“无效选择”的Python Flask WTForm SelectField [英] Python Flask WTForm SelectField with Enum values 'Not a valid choice' upon validation
问题描述
我的Python Flask应用程序正在使用具有内置python Enum支持的WTForms。我正在尝试提交一个表单(POST),其中一个Enum的所有值填充一个SelectField。
My Python Flask app is using WTForms with built in python Enum support. I'm attempting to submit a form (POST) where a SelectField is populated by all values of a Enum.
当我点击提交时,出现错误消息无效选择。这似乎很奇怪,因为在检查传入表单的值时,该表单似乎确实从提供的Enum值列表中包含一个有效的选择。
When I hit 'Submit' i'm given the error, 'Not a valid choice.' This seems strange because when checking the values of the incoming form, the form seemingly does contain a valid choice from the list of Enum values provided.
我正在使用名为 AJBEnum $ c $的Enum子类。 c>的格式如下:
I'm using a subclass of Enum named AJBEnum
which is formatted like so:
class UserRole(AJBEnum):
admin = 0
recipient = 1
我之所以选择这样做,是因为我在项目中使用了许多枚举,并想编写一个助手收集所有选择并格式化它们的函数WTForm SelectField元组友好。 AJBEnum的格式如下:
I chose to do this because I use many Enums through the project and wanted to write a helper function that gathers all choices and formats them WTForm SelectField tuple friendly. AJBEnum is formatted like so:
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
的所有选择,例如:
Which means I can give WTForms all choices for UserRole
during the creating of the SelectField like so:
role = SelectField('Role', choices=UserRole.choices(blank=False), default=UserRole.recipient)
注意函数参数 blank
提供了一个附加的空白SelectField选项,以防SelectField是可选的。在这种情况下,不是。
Note the function parameter blank
provides an additional blank SelectField option in case the SelectField is optional. In this case, it is not.
当我点击提交按钮时,我会检查路径中的传入请求并通过打印表格来检查。数据
,我得到了以下内容:
When I hit the Submit button I check the incoming incoming request in my routes and by printing the form.data
i'm given this content:
{'email': 'abc@gmail.com', 'password': 'fake', 'plan': 'A', 'confirm': 'fake', 'submit': True, 'id': None, 'role': 'UserRole.recipient'}
看来WTForms已将UserRole.recipient字符串化。有没有一种方法可以迫使WTForms将传入的POST请求值转换回原来的Enum值?
As you can see, it appears WTForms has stringified UserRole.recipient. Is there a way to coerce WTForms into converting the incoming POST request value back to the Enum value that it was intended to be?
推荐答案
是否可以强制转换WTForms
Is there a way to coerce WTForms
您要查找的参数实际上称为 coerce
,它接受将字段的字符串表示形式转换为选择值的可调用对象。
The argument you're looking for is actually called coerce
, and it accepts a callable that converts the string representation of the field to the choice's value.
- 选择值应为
Enum
实例 - 字段值应为
str(Enum。值)
- 字段文本应为
Enum.name
- The choice value should be an
Enum
instance - The field value should be
str(Enum.value)
- The field text should be
Enum.name
要完成此操作,我用一些 WTForms $ c $扩展了
Enum
c>助手:
To accomplish this, I've extended Enum
with some WTForms
helpers:
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
派生的值c $ c> SelectField :
You can then edit a FormEnum
derived value using a SelectField
:
role = SelectField(
"Role",
choices = UserRole.choices(),
coerce = UserRole.coerce)
这篇关于验证后具有Enum值“无效选择”的Python Flask WTForm SelectField的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!