python - Flask WTForms 动态选择字段验证值在 POST 上为空
问题描述
我无法验证动态生成的 WTForms SelectField。不知何故,我self.choices
在 POST 期间是空的,而它们在第一个 GET 请求中填充。我错过了什么吗?
应用程序.py:
@app.route('/users/edit/<email>/', methods=['GET', 'POST'])
def users_edit(email):
match = False
for user in session['users']['message']:
if user['email']['S'] == email:
match = True
if match:
form = EditUserForm()
if request.method == 'GET':
form_data = session.get('edit_user_form_data', None)
if form_data:
form = EditUserForm(MultiDict(form_data))
form.shops_allowed.choices = [(str(shop['shop_id']['S']), str(shop['general']['M']['shop_name']['S'])) for i, shop in enumerate(session['shops']['message'])]
print(f"SHOPS_ALLOWED CHOICES WITH FORM DATA: {form.shops_allowed.choices}")
form.validate()
session.pop('edit_user_form_data', None)
else:
form.email.data = email
form.shops_allowed.choices = [(str(shop['shop_id']['S']), str(shop['general']['M']['shop_name']['S'])) for i, shop in enumerate(session['shops']['message'])]
print(f"SHOPS_ALLOWED CHOICES WITHOUT FORM DATA: {form.shops_allowed.choices}")
matched_shop = []
for user in session['users']['message']:
if user['email']['S'] == email and 'shops_allowed' in user.keys():
matched_shop = [allow['S'] for allow, shop in zip(user['shops_allowed']['L'], session['shops']['message'])]
form.shops_allowed.data = matched_shop
form.validate()
if request.method == 'POST' and form.validate_on_submit():
app.logger.info(f"PRE POST EDIT USER FORM DATA: {form.data}")
url = ...
<REDACTED POST REQUESTS ENDPOINT>
app.logger.info(f"POST EDIT USER RESPONSE: ({post_response.status_code}) {response_data}")
if post_response.status_code == 200:
session.pop('edit_user_form_data', None)
return redirect(url_for('users'))
else:
app.logger.info(f"EDIT USER FORM DATA: {form.data}")
session['edit_user_form_data'] = form.data
return redirect(url_for('users_edit', email=email))
elif request.method == 'POST' and form.validate_on_submit() == False:
app.logger.info(f"EDIT USER FORM DATA VALIDATION FAILED: {form.data}")
session['edit_user_form_data'] = form.data
return redirect(url_for('users_edit', email=email))
表格.py
class NonValidatingSelectMultipleField(SelectMultipleField):
def __len__(self):
return 1
def pre_validate(self, form):
pass
# HACK TO VALID A CHOICE FOR SELECT MULTIPLE
if self.data:
print(f"SELF DATA: {self.data}")
print(f"VALUES: {self.choices}")
values = list(self.coerce(c[0]) for c in self.choices)
print(f"PROCESSED VALUES: {values}")
for d in self.data:
if d not in values:
raise ValueError(self.gettext("'%(value)s' is not a valid choice for this multiple select field") % dict(value=d))
class EditUserForm(FlaskForm):
email = StringField('Email', [
validators.DataRequired(),
validators.Length(min=6),
validators.Email(message='Not a valid email address.')]
)
shops_allowed = NonValidatingSelectMultipleField(
'Shops',
widget = widgets.ListWidget(prefix_label=False),
option_widget = widgets.CheckboxInput(),
coerce=str
)
这将呈现以下日志记录:
SHOPS_ALLOWED CHOICES WITHOUT FORM DATA: [('decb5a00-fe45-484f-b887-b9bd41c4f0f2', 'My shop'), ('2cea2efa-7ccf-4bca-896d-16119d5fb7a8', 'My other shop')]
SELF DATA: ['decb5a00-fe45-484f-b887-b9bd41c4f0f2', '2cea2efa-7ccf-4bca-896d-16119d5fb7a8']
VALUES: [('decb5a00-fe45-484f-b887-b9bd41c4f0f2', 'My shop'), ('2cea2efa-7ccf-4bca-896d-16119d5fb7a8', 'My other shop')]
PROCESSED VALUES: ['decb5a00-fe45-484f-b887-b9bd41c4f0f2', '2cea2efa-7ccf-4bca-896d-16119d5fb7a8']
127.0.0.1 - - [03/Apr/2020 14:30:11] "GET /users/edit/my@email.com/ HTTP/1.1" 200 -
发布后:
SELF DATA: ['decb5a00-fe45-484f-b887-b9bd41c4f0f2', '2cea2efa-7ccf-4bca-896d-16119d5fb7a8']
VALUES: None
在屏幕上:
forms.py", line 35, in pre_validate values = list(self.coerce(c[0]) for c in self.choices) TypeError: 'NoneType' object is not iterable
解决方案
嗯,在再次查看我的代码后,我终于找到了问题所在。我打电话form.validate_on_submit()
的同时我正在验证if request.method == 'POST'
这永远不会让我有可能在 POST 期间填充选择。
将我的代码更改为:
if request.method == 'POST':
form.shops_allowed.choices = [(str(shop['shop_id']['S']), str(shop['general']['M']['shop_name']['S'])) for i, shop in enumerate(session['shops']['message'])]
form.validate_on_submit()
它开始起作用了。有时你只需要写下来就能看到答案:-)
推荐阅读
- python - 这个python程序是做什么的?是老鼠吗?
- c++ - 服务器未从客户端接收。Linux TCP/IP 通信
- javascript - 焦点样式在反应组件中无法正常工作?
- python - 使用 systemd 运行的 Python 脚本无法启动 gedit
- tensorflow - 在深度学习中无法序列化大于 4 GiB 的字节对象
- r - R 函数 POSIXct 无法识别我的文件的时间格式
- ncurses - Ncurses中的换行符后如何防止光标回到屏幕的最左侧?
- video - 与 ffmpeg 的视频连接给出了不正确的持续时间
- javascript - 如何以角度选择输入类型文本的最后一个子项?
- javascript - 在没有任何 mapstatetoprops 的情况下连接 redux 并且仍然将东西作为道具