ISO Help: Nested Form Submission in Flask
Tags: help, flask, html, beginners
Published: 2024-05-08 22:28:16

**UPDATE: [SOLVED: Nested Form Submission in Flask](https://dev.to/francheese9289/solved-nested-form-submission-in-flask-2j8n)**

Note - I'm a new coder, so thanks for bearing with me!

**My Project**
I'm trying to create an organization centric data entry & analysis site for my capstone project. The parameters are ones that I set based on a real need we had at my last place of employment (public school district).

**The Problem**
I've been torturing myself trying to build a data-input table for users to enter student scores for various diagnostics/assessments and their individual components (i.e. a certain literacy assessment may test reading and writing separately). I'm working in Flask with Flask Forms and WTForms, my front end is using Bulma CSS.

Well hallelujah I've almost made it, but I have a few issues, the biggest and most immediate is that I can't figure out the syntax for submitting my nested form data. 

`forms.py`
```
class ComponentForm(Form):
    component_id = HiddenField('Component ID')
    component = HiddenField('Component')
    score = FloatField('Score', default=0.0, widget=NumberInput())

class AssessmentScoreForm(FlaskForm):
    student_id = HiddenField(u'Student ID') 
    assessment_name=HiddenField(u'Assessment Name')
    period = SelectField("Choose an option", validate_choice=False, choices={'1':'fall','2':'winter','3':'spring'}) 
    components = FieldList(FormField(ComponentForm))
    submit = SubmitField()
```

As it stands, I've been able to render a table that has columns representing each assessment component and rows representing each student. From my page source and from playing around with the labels, I can see that each cell is correctly associated with a student and a component. 

![Screenshot of data entry page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yy1a2cnkg4ep0mjbcpx5.png)

Trouble is, when I go to submit, I'm receiving an error regarding the score field, which is in my nested `ComponentForm`.

Here is my code for rending the page:

`data_entry.py`

```
@api.route('/data_entry', methods=['GET', 'POST'])
def data_entry():
    #find current user adn their most recent classroom
    user=current_user
    staff = db.session.scalar(sa.select(Staff).where(Staff.id == user.staff_id))
    current_class = staff.staff_classrooms[-1] #classroom object
    assessment = 'Predictive Assessment of Reading' #will be a variable

    #gather information for all students in that classroom
    students = current_class.class_students
    roster_data = []
    for student in students:
        roster_data.append({
            'id': student.class_student.id,
            'full_name': student.class_student.full_name
        })
    
    components = db.session.scalars(sa.select(AssessmentComponent).where(AssessmentComponent.assessment_name == assessment).order_by(AssessmentComponent.component_name)).all()
    form = AssessmentScoreForm()
    component_form = ComponentForm()
    for component in components:
        component_form.component_id = component.id
        component_form.component = component.component_name

        form.components.append_entry(component_form)

    for student in students:
        form.student_id.data = student.class_student.id
        if form.validate_on_submit():
            #create score instance and set period, student_id, classroom_id
            for i in enumerate(form.components.entries): 
                new_score = AssessmentScore()
                new_score.student_score = form.components.entries[i]['score'].data #score 
                new_score.period = form.period.data #period
                new_score.component_id = form.components.entries[i]['component_id'].data  #component
                new_score.student_id = student.class_student.id #student
                new_score.classroom_id = current_class.id #classroom
                    
                print (f'score_instance {new_score}')

                db.session.add(new_score)
                db.session.commit()
                flash('Data entered successfully!','success')
                return redirect('main.user', username=user.username)

    return render_template('data_entry.html', form=form, components=components, roster_data=roster_data)
```


**Attempt 1**

```
        if form.validate_on_submit():
            #create score instance and set period, student_id, classroom_id
            new_score = AssessmentScore()
            new_score.student_score = form.score.data #score
```
**Error 1**
`AttributeError: 'AssessmentScoreForm' object has no attribute 'score'`

**Attempt 2**

```
if form.validate_on_submit():
            #create score instance and set period, student_id, classroom_id
            for component in form.components:
                new_score = AssessmentScore()
                new_score.student_score = form.components.score.data
```
**Error 2**
`AttributeError: 'FieldList' object has no attribute 'score'`

**Attempt 3**
```
        if form.validate_on_submit():
            for i in enumerate(form.components.entries): 
                new_score = AssessmentScore()
                new_score.student_score = form.components.entries[i]['score'].data  
```
**Error 3**
`TypeError: list indices must be integers or slices, not tuple`

**What Else I've Tried**
I've had many other iterations of this and even tried to use Plot.ly Dash to make an editable table, but with my limited knowledge, I'm not sure how to make this work.

Also, there are a TON of questions on stackoverflow regarding WTForms and, specifically, FieldList and FormField, most of them haven't been edited in 8-10 years, haven't been solved and/or aren't addressing the same issue. The WTForms documentation is also lacking in examples and lord help me if I read another tutorial on how to login and logout (jk I'm probably just using the wrong tool).

That being said, I've been hacking at this way too long and would send a million roses (in my thoughts) to whomever can help me out.


**p.s.**
I'm also open to conversation regarding other tools (what should I learn when I'm done with my course?) and/or alternative strategies/ deeper discussion about the tools I am using. i.e. Is writing documentation for WTForms a thing that would be cool? Would making a new function for forms be worth it? Is there some WTForms/NumPy/Pandas lovechild waiting to be born so the layman can make a silly little table? I'm wide-eyed and curious.