2015-04-08 28 views
13

Ho un'app Flask in cui posso popolare i dati del modulo caricando un file CSV che viene poi letto. Voglio popolare una FieldList con i dati letti dal CSV. Tuttavia, quando provo a popolare i dati, inserisce HTML grezzo nei campi di testo anziché solo il valore che voglio. Che cosa sto facendo di sbagliato?Filling WTForms FieldField FieldList con i risultati dei dati in HTML nei campi

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> 

Il frammento di codice offendere succede alla linea classform.students.append_entry(studentform). Posso postare l'output HTML se richiesto. Quello che mi aspetto è qualcosa di simile: Expected Output Cosa ottengo invece è: enter image description here

risposta

23

OK, ho passato ore su questo e alla fine è stato un tale cambiamento di codice banale.

La maggior parte dei campi consente di modificare il loro valore modificando l'attributo data (come stavo facendo in precedenza). In realtà, nel mio codice, ho avuto questo commento come sopra:

### 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) 

Tuttavia, nel caso di un FieldList di FormField, non dovremmo modificare l'attributo data, ma piuttosto il campo stesso. Il seguente codice funziona come previsto:

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) 

Spero che questo aiuti qualcuno che si verifica lo stesso problema.

+0

Non so che tu abbia un senso con l'esempio di lavoro autonomo completo? –

+1

Un esempio con questo esempio è [qui] (https://gist.github.com/adeadman/62bceb59bbf5a5652eacdc51dc15c24f). –

+0

Impressionante, l'ho implementato nel modo sbagliato e stavo facendo un sacco di tempo a popolarsi dal database per la modifica. Grazie per la pubblicazione! –