我正在使用model_form从App Engine模型自动创建表单。它工作正常,但创建的表单不包括ListProperty()字段。 代码段:
在models.py中:
class Team(db.Model):
name = db.StringProperty()
members = db.ListProperty(db.Key)
在views.py中:
def test_app():
form = model_form(Team)
app.logger.debug("form :" + str(dir(form)))
return render_template("some_template.html")
dir(form)未显示字段'members',它是ListProperty()。我不能在模板中使用'form.members',因为表单没有'members'属性。
我在http://wtforms.simplecodes.com/docs/1.0.3/ext.html中看到ListProperty没有等效的'Field'。如何处理这些模型?
答案 0 :(得分:1)
WTforms没有为App Engine的ListProerty提供等效的“Field”,而model_form正在跳过“members”字段。那么,我们如何在'members'数据存储区域中存储'db.Key'实例。在这个问题上花了很多时间后,我终于能够在成员字段中存储'db.Key'实例。代码片段如下:
models.py:
class Team(db.Model):
members = db.ListProperty(db.Key)
由于成员存储所有可用成员的“db.Key”实例。显示的表单应该有多个选择字段,以便用户可以选择多个成员。我使用WTforms来做到这一点。
forms.py:
class TeamForm(wtf.Form):
members = wtf.SelectMultipleField('Members', validators=[validators.Required()])
views.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实例是将以unicode的形式发送到html表单的实例。因此,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'实例。希望它对某人有所帮助,如果有更好的方法请告诉我。