sec*_*119 15 python subclassing wtforms
我有一个UserForm类:
class UserForm(Form):
first_name = TextField(u'First name', [validators.Required()])
last_name = TextField(u'Last name', [validators.Required()])
middle_name = TextField(u'Middle name', [validators.Required()])
username = TextField(u'Username', [validators.Required()])
password = TextField(u'Password', [validators.Required()], widget=PasswordInput())
email = TextField(u'Email', [validators.Optional(), validators.Email()])
Run Code Online (Sandbox Code Playgroud)
并希望在UpdateUserForm中使密码字段成为可选:
class UpdateUserForm(UserForm):
password = TextField(u'Password', [validators.Optional()], widget=PasswordInput())
Run Code Online (Sandbox Code Playgroud)
但密码字段位于电子邮件字段之后,而不是之前.
如何在子类化时保留字段顺序?
此外,当我尝试更改密码字段验证器时它不起作用 - 密码仍然是必需的:/为什么?
class UpdateUserForm(UserForm):
def __init__(self, **kwargs):
self.password.validators = [validators.Optional()]
super(UpdateUserForm, self).__init__(**kwargs)
Run Code Online (Sandbox Code Playgroud)
要么
class UpdateUserForm(UserForm):
def __init__(self, **kwargs):
self.password = TextField(u'Password', [validators.Optional()], widget=PasswordInput())
super(UpdateUserForm, self).__init__(**kwargs)
Run Code Online (Sandbox Code Playgroud)
class UpdateUserForm(UserForm):
def __init__(self, formdata=None, obj=None, prefix='', **kwargs):
self._unbound_fields[4][1] = TextField(u'Password', [validators.Optional()], widget=PasswordInput())
UserForm.__init__(self, formdata=None, obj=None, prefix='', **kwargs)
Run Code Online (Sandbox Code Playgroud)
最后,我需要的是:
class UpdateUserForm(UserForm):
def __init__(self, formdata=None, obj=None, prefix='', **kwargs):
UserForm.__init__(self, formdata, obj, prefix, **kwargs)
self['password'].validators = [validators.Optional()]
self['password'].flags.required = False
Run Code Online (Sandbox Code Playgroud)
rhy*_*yek 12
关于在迭代表单对象时重写字段的第一个问题,这就是我所做的:
class BaseForm(Form):
def __iter__(self):
field_order = getattr(self, 'field_order', None)
if field_order:
temp_fields = []
for name in field_order:
if name == '*':
temp_fields.extend([f for f in self._unbound_fields if f[0] not in field_order])
else:
temp_fields.append([f for f in self._unbound_fields if f[0] == name][0])
self._unbound_fields = temp_fields
return super(BaseForm, self).__iter__()
class BaseUserForm(BaseForm):
password = PasswordField('Password', [Required()])
full_name = TextField('Full name', [Required()])
class NewUserForm(BaseUserForm):
username = Textfield('Username', [Required()])
field_order = ('username', '*')
Run Code Online (Sandbox Code Playgroud)
这样,当你渲染NewUserForm(可能是从一个模板,在形式的字段呈现场迭代),你会看到username,password,full_name.通常你会看到username最后一个.
发生这种情况是因为字段排序是由 UnboundField.creation_counter 类定义的,该类使用 Field 类在代码中出现的顺序。
>>> x1 = UserForm()
>>> x2 = UpdateUserForm()
>>> [(f[0], f[1].creation_counter) for f in x1._unbound_fields]
[('first_name', 22), ('last_name', 23), ('middle_name', 24), ('username', 25), ('password', 26), ('email', 27)]
>>> [(f[0], f[1].creation_counter) for f in x2._unbound_fields]
[('first_name', 22), ('last_name', 23), ('middle_name', 24), ('username', 25), ('email', 27), ('password', 28)]
>>>
Run Code Online (Sandbox Code Playgroud)
由于这个问题很难解决(因为 wtforms 试图使用这种方法变得神奇),所以处理这个问题的最佳方法是按所需的顺序定义字段。
class BaseForm(Form):
first_name = TextField(u'First name', [validators.Required()])
last_name = TextField(u'Last name', [validators.Required()])
middle_name = TextField(u'Middle name', [validators.Required()])
username = TextField(u'Username', [validators.Required()])
class UserForm(BaseForm):
password = TextField(u'Password', [validators.Required()], widget=PasswordInput())
email = TextField(u'Email', [validators.Optional(), validators.Email()])
class UpdateUserForm(BaseForm):
password = TextField(u'Password', [validators.Optional()], widget=PasswordInput())
email = TextField(u'Email', [validators.Optional(), validators.Email()])
Run Code Online (Sandbox Code Playgroud)
但如果您是完美主义者或需要遵守DRY 原则:
class BaseForm(Form):
first_name = TextField(u'First name', [validators.Required()])
last_name = TextField(u'Last name', [validators.Required()])
middle_name = TextField(u'Middle name', [validators.Required()])
username = TextField(u'Username', [validators.Required()])
class UserForm(BaseForm):
password = TextField(u'Password', [validators.Required()], widget=PasswordInput())
class UpdateUserForm(BaseForm):
password = TextField(u'Password', [validators.Optional()], widget=PasswordInput())
BaseForm.email = TextField(u'Email', [validators.Optional(), validators.Email()])
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7158 次 |
| 最近记录: |