How to add data from flask_sqlalchemy orm to WTForm FieldList?

365 Views Asked by At

I want to set up a website using flask, WTForm and flask_sqlalchemy. There is a web page for users to submit information by WTForm and now I want to create another page to display all the data in the database.I want to use WTForm to do this.In one book,the example is as follow:

def GetSchoolFormById(school_id):
    school = orm.School.query.get(int(school_id))
    if school is None:
        return None
    schoolform = SchoolForm()
    schoolform.id.data = school.id
    schoolform.name.data = school.name
    schoolform.area_id.data = school.area_id
    schoolform.area_name = school.area.name
    schoolform.teachdesc.data = school.teachdesc
    schoolform.address.data = school.address
    schoolform.schooltype_id.data = school.schooltype_id
    schoolform.schooltype_name = school.schooltype.name
    schoolform.website.data = school.website
    schoolform.distinguish.data = school.distinguish
    schoolform.leisure.data = school.leisure
    schoolform.threashold.data = school.threashold
    schoolform.partner.data = school.partner
    schoolform.artsource.data = school.artsource
    schoolform.feedesc.data = school.feedesc
    schoolform.longitude.data = school.longitude
    schoolform.latitude.data = school.latitude
    schoolform.schoolimages = school.schoolimages
    schoolform.feature_ids.data = [x.feature_id for x in school.schoolfeatures]

    schoolform.area_id.choices = g_choices_area
    schoolform.schooltype_id.choices = g_choices_schooltype
    schoolform.feature_ids.choices = g_choices_feature
    return schoolform

but as for me,I used FieldList,so I don't know how to add data like the example.

class ProjectForm(FlaskForm):
    project_id = HiddenField('项目ID')
    project_name = StringField('工程名称')
    project_ST = DateField('起始时间', format='%Y-%m-%d')
    project_FT = DateField('截止时间', format='%Y-%m-%d')


class ItemsForm(Form):
    item_id = HiddenField('事件ID')
    item_name = StringField('事件名称')
    pre_item = SelectMultipleField('前驱事件')
    # 暂定为string类型,加到date的%d里,具体我也不会,实现不了可以再改
    last_time = StringField('持续时间')


class MainForm(FlaskForm):
    items = FieldList(
        FormField(ItemsForm)
    )
@app.route('/view_items', methods=['GET', 'POST'])
def view_items():
    form_one = ProjectForm()
    form_two = MainForm()
    if request.method == 'GET':
        project = DBProject.query.filter_by(project_id=1).first().__dict__
        print(project)
        # 由于目前只有一个project,所以直接导入全部items数据
        items = list(DBItem.query.filter().all())

        form_one.project_id.data = project['project_id']
        form_one.project_name.data = project['project_name']
        form_one.project_ST.data = project['project_ST']
        form_one.project_FT.data = project['project_FT']

        for item in items:
            print(item)
            form_two.items.append_entry(ItemsForm(item))
    return render_template('view_items.html', form_one=form_one, form_two=form_two)

When I test my code,there is an error for the second line from the bottom like this:

TypeError: formdata should be a multidict-type wrapper that supports the 'getlist' method

How can I deal with it?should I use other method to deliver data to the html page instead of WTForm?

1

There are 1 best solutions below

0
EAW On

The arguments to the __init__ method of a WTForms Form are as follows __init__(formdata=None, obj=None, prefix='', data=None, meta=None, **kwargs). You are passing an Sqlalchemy object as the formdata argument which is intended to receive the users form data sent via a http post as a Werkzeug Multidict. If you pass the object as the obj argument instead then it should work as long as the database column names match the form field names. You can also use this technique to initialise your ProjectForm rather than setting the data for each field in turn.

project = DBProject.query.filter_by(project_id=1).first()
form_one = ProjectForm(obj=project)

items = list(DBItem.query.filter().all())
for item in items:
    form_two.items.append_entry(ItemsForm(obj=item))