2015-04-08 5 views
13

Ich habe eine Flask-App, in der ich Formulardaten durch Hochladen einer CSV-Datei ausfüllen kann, die dann gelesen wird. Ich möchte eine FieldList mit den aus der CSV gelesenen Daten füllen. Wenn ich jedoch versuche, die Daten zu füllen, gibt es in den TextFields raw HTML statt nur den Wert ein, den ich möchte. Was mache ich falsch?Füllen von WTForms FormField FieldList mit Daten in HTML in Felder

app.py

from flask import Flask, render_template, request, url_for 
from flask.ext.wtf import Form 
from wtforms import StringField, FieldList, FormField, SelectField 
from wtforms.validators import DataRequired 
from werkzeug.datastructures import MultiDict 

app = Flask(__name__) 
app.config['SECRET_KEY']='asdfjlkghdsf' 

# normally student data is read in from a file uploaded, but for this demo we use dummy data 
student_info=[("123","Bob Jones"),("234","Peter Johnson"),("345","Carly Everett"), 
       ("456","Josephine Edgewood"),("567","Pat White"),("678","Jesse Black")] 

class FileUploadForm(Form): 
    pass 

class StudentForm(Form): 
    student_id = StringField('Student ID', validators = [DataRequired()]) 
    student_name = StringField('Student Name', validators = [DataRequired()]) 

class AddClassForm(Form): 
    name = StringField('classname', validators=[DataRequired()]) 
    day = SelectField('classday', 
         choices=[(1,"Monday"),(2,"Tuesday"),(3,"Wednesday"),(4,"Thursday"),(5,"Friday")], 
         coerce=int) 

    students = FieldList(FormField(StudentForm), min_entries = 5) # show at least 5 blank fields by default 

@app.route('/', methods=['GET', 'POST']) 
def addclass(): 
    fileform = FileUploadForm() 
    classform = AddClassForm() 

    # Check which 'submit' button was called to validate the correct form 
    if 'addclass' in request.form and classform.validate_on_submit(): 
     # Add class to DB - not relevant for this example. 
     return redirect(url_for('addclass')) 

    if 'upload' in request.form and fileform.validate_on_submit(): 
     # get the data file from the post - not relevant for this example. 
     # overwrite the classform by populating it with values read from file 
     classform = PopulateFormFromFile() 
     return render_template('addclass.html', classform=classform) 

    return render_template('addclass.html', fileform=fileform, classform=classform) 

def PopulateFormFromFile(): 
    classform = AddClassForm() 

    # normally we would read the file passed in as an argument and pull data out, 
    # but let's just use the dummy data from the top of this file, and some hardcoded values 
    classform.name.data = "Super Awesome Class" 
    classform.day.data = 4 # Thursday 

    # pop off any blank fields already in student info 
    while len(classform.students) > 0: 
     classform.students.pop_entry() 

    for student_id, name in student_info: 
     # either of these ways have the same end result. 
     # 
     # studentform = StudentForm() 
     # studentform.student_id.data = student_id 
     # studentform.student_name.data = name 
     # 
     # OR 
     student_data = MultiDict([('student_id',student_id), ('student_name',name)]) 
     studentform = StudentForm(student_data) 

     classform.students.append_entry(studentform) 

    return classform 


if __name__ == '__main__': 
    app.run(debug=True, port=5001) 

templates/addclass.html

<html> 
    <head> 
     <title>Flask FieldList Demo</title> 
    </head> 
    <body> 
     <h1>Add Class</h1> 
     {% if fileform %} 
     <div> 
      <p>Add class from file:</p> 
      <form action="" method="post" enctype="multipart/form-data" name="fileform"> 
       {{ fileform.hidden_tag() }} 
       <p><input type="submit" name="upload" value="Upload"></p> 
      </form> 
     </div> 
     <hr> 
     {% endif %} 
     <div> 
      <form action="" method="post" name="classform"> 
       {{ classform.hidden_tag() }} 
       Class Name: {{ classform.name }}<br> 
       Day: {{ classform.day }}<br> 
       <br> 
       <div> 
        <table> 
         <tr> 
          <th> Student Number </th> 
          <th> Name </th> 
         </tr> 
         {% for student in classform.students %} 
         <tr> 
          <td>{{ student.student_id }}</td> 
          <td>{{ student.student_name }}</td> 
         </tr> 
         {% endfor %} 
        </table> 
       </div> 
       <p><input type="submit" name="addclass" value="Add Class"></p> 
      </form> 
     </div> 
    </body> 
</html> 

Die Schnipsel problematischen Code in der Zeile geschieht classform.students.append_entry(studentform). Ich kann die Ausgabe HTML bei Bedarf veröffentlichen. Was ich erwarte, ist so etwas wie diese: Expected Output Was ich stattdessen: enter image description here

Antwort

23

OK, ich verbrachte Stunden auf diesem und am Ende war es ein solche triviale Codeänderung.

In den meisten Feldern können Sie ihren Wert ändern, indem Sie das Attribut data (wie oben) ändern. In der Tat, in meinem Code, ich hatte diesen Kommentar wie oben:

### either of these ways have the same end result. 
    # 
    # studentform = StudentForm() 
    # studentform.student_id.data = student_id 
    # studentform.student_name.data = name 
    # 
    ### OR 
    # 
    # student_data = MultiDict([('student_id',student_id), ('student_name',name)]) 
    # studentform = StudentForm(student_data) 

jedoch im Fall einer Fieldlist von Formfields, sollten wir das data Attribut nicht bearbeiten, sondern das Feld selbst. Der folgende Code funktioniert wie erwartet:

for student_id, name in student_info: 

    studentform = StudentForm() 
    studentform.student_id = student_id  # not student_id.data 
    studentform.student_name = name 

    classform.students.append_entry(studentform) 

Ich hoffe, dies hilft jemandem das gleiche Problem zu erleben.

+0

Ich bin nicht der Meinung, dass Sie mit dem vollständigen Standalone-Beispiel arbeiten? –

+1

A gist mit dem Beispiel dieser Arbeit ist [hier] (https://gist.github.com/adeadman/62bceb59bbf5a5652eacdc51dc15c24f). –

+0

Ehrfürchtig, ich habe dies falsch implementiert und es fiel mir sehr schwer, Daten aus der Datenbank zu bearbeiten. Danke fürs Schreiben! –