简体   繁体   English

WTForm FormField填充值

[英]WTForm FormField populate values

I have a problem with setting default values of a FieldForm in WTForms. 我在WTForms中设置FieldForm的默认值时遇到问题。

models.py 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 contains only attributes which match the Product db Model. ProductBase仅包含与Product db模型匹配的属性。
forms.py 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')

The add_repairs contains a form which I want to use in the view to create Repairs. add_repairs包含一个我想在视图中用于创建维修的表格。 The base_product is a form to which, ideally, I want to pass a obj=product in the views, so the default values get populated automatically. base_product是一种表单,理想情况下,我想在视图中传递obj = product,因此默认值会自动填充。 I want to use the form.populate_obj() as well, just on the base_product form. 我也想在base_product表单上使用form.populate_obj()。

here's how I create the Product form in the view: 这是我如何在视图中创建产品表单的方法:

def make_product_form(form=None, product=None, **kwargs):
    form = form()
    form.base_product.obj = product        
    return form

And then, when handling POSTs, I want to do: 然后,在处理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)

However, the base_form from the Product form, doesn't get filled with default values from an existing object. 但是,Product表单中的base_form不会被现有对象的默认值填充。

Any suggestions on how to achieve this? 关于如何实现这一目标的任何建议? Thanks :) 谢谢 :)

Use form process method to populate form fields with object's attributes values. 使用表单process方法用对象的属性值填充表单字段。
Use form populate_obj method to populate object's attributes with values from form fields. 使用表单populate_obj方法用表单字段中的值填充对象的属性。
Note: names of object's attributes must match names with form fields. 注意:对象属性的名称必须与表单字段的名称匹配。

process example: 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 example: 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"

After discovering that you can run code directly from the Flask's stack trace in the browser(how cool is that?), I found a solution to my problem. 发现可以直接在浏览器中的Flask堆栈跟踪中运行代码之后(这有多酷?),我找到了解决问题的方法。

The key is that when creating the main Product form(in make_product_form()), when I do 关键是当我创建主产品表单(在make_product_form()中)时,
form.base_product.obj I don't really access the obj attribute. form.base_product.obj我实际上并没有访问obj属性。

However, doing form.base_product.form.process(obj=product) did the trick! 但是,执行form.base_product.form.process(obj=product)达到目的! The key is using the base_product. 关键是使用base_product。 form in order to get access to the form within the FormField. 表单 ,以便在FormField中访问表单。 Here are all the attribututes of form.base_product. 这是form.base_product的所有属性。 The dir() is evaluated just after the form=form() in the make_product_form(): 在make_product_form()中,仅在form = form()之后评估dir():

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' ]

What this shows is that actually form.base_product is a Field, not a Form,and doing form.base_product.form got me the ProductBase form. 这表明实际上form.base_product是一个Field,而不是Form,执行form.base_product.form使我获得了ProductBase表单。

Hope this is helpful 希望这会有所帮助

**Update ** **更新 **
I had to use the process(obj=product) only on GET requests, to prepopulate the form, otherwise on POST, the actual form data is discarded. 我只能在GET请求上使用process(obj = product)来预先填充表单,否则在POST上,实际的表单数据将被丢弃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM