0

我正在使用 model_form 从 App Engine 模型自动创建表单。它工作正常,但创建的表单不包含 ListProperty() 字段。代码片段:

在模型.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) 未显示 ListProperty() 字段“成员”。我不能在模板中使用“form.members”,因为表单没有“members”属性。

我在http://wtforms.simplecodes.com/docs/1.0.3/ext.html中看到ListProperty 没有等效的“字段”。如何处理这些模型?

4

1 回答 1

1

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' 实例。希望它对某人有所帮助,如果有更好的方法,请告诉我。

于 2013-04-30T12:42:01.383 回答