WTForm FormField 填充值
WTForm FormField populate values
我在 WTForms 中设置 FieldForm 的默认值时遇到问题。
models.py
class RepairCategory(db.Model):
name = ...
class Repair(db.Model):
price = ..
category_id [FK] = ...
product_id [FK]
class Product(db.Model):
name = ...
description = ...
color = ...
ProductBase 仅包含与产品数据库模型匹配的属性。
forms.py
class NewRepair(Form):
#this is okay - it get's populated
repair_category = QuerySelectField("Repair category",
query_factory=get_categories)
price = DecimalField()
class ProductBase(Form):
name = StringField("Name ", validators=[DataRequired(), Length(1, 64)])
color = StringField("Color ", validators=[DataRequired(), Length(1, 64)])
description = TextAreaField("Description")
active = BooleanField()
class Product(Form):
base_product = FormField(ProductBase)
add_repairs = FormField(NewRepair)
submit = SubmitField('Submit')
add_repairs 包含一个表单,我想在视图中使用它来创建修复。 base_product 是一种形式,理想情况下,我想在视图中传递一个 obj=product ,以便自动填充默认值。我也想使用 form.populate_obj(),只是在 base_product 形式上。
下面是我在视图中创建产品表单的方式:
def make_product_form(form=None, product=None, **kwargs):
form = form()
form.base_product.obj = product
return form
然后,在处理 POST 时,我想做的是:
def product(id):
product = Product.query.get_or_404(id)
form = make_product_form(form=Product,product=product)
if form.validate_on_submit():
product_form = form.base_product
product_form.populate_obj(product)
但是,产品表单中的 base_form 不会填充现有对象的默认值。
关于如何实现这一点有什么建议吗?
谢谢:)
使用表单 process
方法用对象的属性值填充表单字段。
使用表单 populate_obj
方法用表单字段中的值填充对象的属性。
注意:对象属性的名称必须与表单字段的名称相匹配。
process
示例:
>>> class MyObj(object):
... name = "object's name"
>>> from wtforms import Form, StringField
>>> class MyForm(Form):
... name = StringField("Form's name")
>>> my_obj = MyObj()
>>> my_obj.name
"object's name"
>>> my_form = MyForm()
>>> print my_form.name.data
None
>>> my_form.process(obj=my_obj)
>>> my_form.name.data
"object's name"
populate_obj
示例:
>>> my_form.name.data = "Form's name"
>>> my_form.name.data
"Form's name"
>>> my_obj.name
"object's name"
>>> my_form.populate_obj(my_obj)
>>> my_obj.name
"Form's name"
在发现您可以 运行 直接从浏览器中的 Flask 堆栈跟踪代码(这有多酷?)之后,我找到了解决我的问题的方法。
关键是在创建主产品表单时(在 make_product_form() 中),当我这样做时
form.base_product.obj
我并没有真正访问 obj 属性。
但是,form.base_product.form.process(obj=product)
成功了!关键是使用 base_product.form 来访问 FormField 中的表单。
这里是form.base_product的所有属性。 dir() 在 make_product_form() 中的 form=form() 之后被评估:
dir(form.base_product)
[#ommitted some attributes#,
'__weakref__', '_formfield', '_obj', '_run_validation_chain',
'_translations', 'data', 'default', 'description',
'do_not_call_in_templates', 'errors', 'filters', 'flags', 'form',
'form_class', 'gettext', 'id', 'label', 'meta', 'name', 'ngettext',
'object_data', 'populate_obj', 'post_validate', 'pre_validate',
'process', 'process_data', 'process_errors', 'process_formdata',
'raw_data', 'render_kw', 'separator', 'short_name', 'type',
'validate', 'validators', 'widget' ]
这表明实际上 form.base_product 是一个字段,而不是一个表单,并且执行 form.base_product.form 得到了 ProductBase 表单。
希望对您有所帮助
**更新**
我必须仅在 GET 请求上使用 process(obj=product) 来预填充表单,否则在 POST 上,实际表单数据将被丢弃。
我在 WTForms 中设置 FieldForm 的默认值时遇到问题。
models.py
class RepairCategory(db.Model): name = ... class Repair(db.Model): price = .. category_id [FK] = ... product_id [FK] class Product(db.Model): name = ... description = ... color = ...
ProductBase 仅包含与产品数据库模型匹配的属性。
forms.py
class NewRepair(Form):
#this is okay - it get's populated
repair_category = QuerySelectField("Repair category",
query_factory=get_categories)
price = DecimalField()
class ProductBase(Form):
name = StringField("Name ", validators=[DataRequired(), Length(1, 64)])
color = StringField("Color ", validators=[DataRequired(), Length(1, 64)])
description = TextAreaField("Description")
active = BooleanField()
class Product(Form):
base_product = FormField(ProductBase)
add_repairs = FormField(NewRepair)
submit = SubmitField('Submit')
add_repairs 包含一个表单,我想在视图中使用它来创建修复。 base_product 是一种形式,理想情况下,我想在视图中传递一个 obj=product ,以便自动填充默认值。我也想使用 form.populate_obj(),只是在 base_product 形式上。
下面是我在视图中创建产品表单的方式:
def make_product_form(form=None, product=None, **kwargs):
form = form()
form.base_product.obj = product
return form
然后,在处理 POST 时,我想做的是:
def product(id):
product = Product.query.get_or_404(id)
form = make_product_form(form=Product,product=product)
if form.validate_on_submit():
product_form = form.base_product
product_form.populate_obj(product)
但是,产品表单中的 base_form 不会填充现有对象的默认值。
关于如何实现这一点有什么建议吗? 谢谢:)
使用表单 process
方法用对象的属性值填充表单字段。
使用表单 populate_obj
方法用表单字段中的值填充对象的属性。
注意:对象属性的名称必须与表单字段的名称相匹配。
process
示例:
>>> class MyObj(object):
... name = "object's name"
>>> from wtforms import Form, StringField
>>> class MyForm(Form):
... name = StringField("Form's name")
>>> my_obj = MyObj()
>>> my_obj.name
"object's name"
>>> my_form = MyForm()
>>> print my_form.name.data
None
>>> my_form.process(obj=my_obj)
>>> my_form.name.data
"object's name"
populate_obj
示例:
>>> my_form.name.data = "Form's name"
>>> my_form.name.data
"Form's name"
>>> my_obj.name
"object's name"
>>> my_form.populate_obj(my_obj)
>>> my_obj.name
"Form's name"
在发现您可以 运行 直接从浏览器中的 Flask 堆栈跟踪代码(这有多酷?)之后,我找到了解决我的问题的方法。
关键是在创建主产品表单时(在 make_product_form() 中),当我这样做时
form.base_product.obj
我并没有真正访问 obj 属性。
但是,form.base_product.form.process(obj=product)
成功了!关键是使用 base_product.form 来访问 FormField 中的表单。
这里是form.base_product的所有属性。 dir() 在 make_product_form() 中的 form=form() 之后被评估:
dir(form.base_product)
[#ommitted some attributes#,
'__weakref__', '_formfield', '_obj', '_run_validation_chain',
'_translations', 'data', 'default', 'description',
'do_not_call_in_templates', 'errors', 'filters', 'flags', 'form',
'form_class', 'gettext', 'id', 'label', 'meta', 'name', 'ngettext',
'object_data', 'populate_obj', 'post_validate', 'pre_validate',
'process', 'process_data', 'process_errors', 'process_formdata',
'raw_data', 'render_kw', 'separator', 'short_name', 'type',
'validate', 'validators', 'widget' ]
这表明实际上 form.base_product 是一个字段,而不是一个表单,并且执行 form.base_product.form 得到了 ProductBase 表单。
希望对您有所帮助
**更新**
我必须仅在 GET 请求上使用 process(obj=product) 来预填充表单,否则在 POST 上,实际表单数据将被丢弃。