WTforms 没有为 App Engine 的 ListProerty 提供等效的“字段”,并且 model_form 正在跳过“成员”字段。所以,我们如何在“members”数据存储字段中存储“db.Key”实例。在这个问题上花了很多时间之后,我终于能够在成员字段中存储“db.Key”实例。代码片段如下:
模型.py:
class Team(db.Model):
members = db.ListProperty(db.Key)
由于成员存储所有可用成员的“db.Key”实例。显示的表单应该有多个选择字段,以便用户可以选择多个成员。我使用 WTforms 来做到这一点。
表格.py:
class TeamForm(wtf.Form):
members = wtf.SelectMultipleField('Members', validators=[validators.Required()])
视图.py:
class create_team():
form = TeamForm()
form.members.choices = [(u.key(), u.name) for u in Member.all().order('name')]
return render_template("create_team.html", form=form)
HTML 仅呈现表单字段。现在,如果您尝试保存表单,您将收到错误“'sdjfsjdfks23746jhew874' 不是此字段的有效选择”。我深入研究了 WTforms 代码,打开 wtforms/fields/core.py。
class SelectMultipleField(SelectField):
"""
No different from a normal select field, except this one can take (and
validate) multiple choices. You'll need to specify the HTML `rows`
attribute to the select field when rendering.
"""
widget = widgets.Select(multiple=True)
def iter_choices(self):
for value, label in self.choices:
selected = self.data is not None and self.coerce(value) in self.data
yield (value, label, selected)
def process_data(self, value):
try:
self.data = list(self.coerce(v) for v in value)
except (ValueError, TypeError):
self.data = None
def process_formdata(self, valuelist):
try:
self.data = list(self.coerce(x) for x in valuelist)
except ValueError:
raise ValueError(self.gettext('Invalid choice(s): one or more data inputs could not be coerced'))
def pre_validate(self, form):
if self.data:
values = list(c[0] for c in self.choices)
for d in self.data:
if d not in values:
raise ValueError(self.gettext("'%(value)s' is not a valid choice for this field") % dict(value=d))
如您所见,预验证功能正在引发该错误。self.choices 包含您在 views.py 中提供的所有选项,其中包含 [(db.Key instance, member name), ...]。db.Key 实例是将发送到 html 表单但以 unicode 形式发送的实例。因此,self.data 包含每个 db.Key 实例的 unicode 值列表。这就是为什么
if d not in values:
满足此条件,因此引发异常。为了让它工作,我改变了 pre-validate() 函数如下(我不知道还能做什么)
def pre_validate(self, form):
if self.data:
values = list(unicode(c[0]) for c in self.choices)
for d in self.data:
if d not in values:
raise ValueError(self.gettext("'%(value)s' is not a valid choice for this field") % dict(value=d))
现在,将表单日期存储在数据存储区中的 views.py 函数中。用这个:
members = [db.get(data).key() for data in form.members.data if data]
将 unicode 转换为 'db.Key' 实例。希望它对某人有所帮助,如果有更好的方法,请告诉我。