如何更新用户输入给出的csv文件的字段名?

时间:2017-09-06 20:51:44

标签: python html csv flask jinja2

我正在尝试构建一个应用程序,它使用不同数量的列来获取不同的CSV文件。例如,我的CSV文件有大约30列,其字段名称具有特殊字符。所以,我想更新用户给出的字段名称。我有一个看起来像这样的CSV文件:

ques.1,ques.2
3,5
5,1

我想用用户(电视,广播)提供的标题更新列名ques.1, ques.2

的Python:

def upload():
    if request.method == 'POST':
        # check if the post request has the file part
        if 'file' not in request.files:
            flash('No file part')
            return redirect(request.url)
        file = request.files['file']

        # if user does not select file, browser also
        # submit a empty part without filename
        if file.filename == '':
            flash('No selected file')
            return redirect(request.url)

        if file and allowed_file(file.filename):
            app.logger.info('File Saved')

            filename = secure_filename(file.filename)
            savepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            flash(savepath)
            file.save(savepath)

            save_in(savepath)

            return redirect(url_for('upload', filename=filename))

    return render_template('pages/placeholder.upload.html') 
def save_in(savepath):
    app.logger.info(savepath)

    csv_rows = []

    with open(savepath) as csvfile:
        reader = csv.DictReader(csvfile)
        title = reader.fieldnames
        for row in reader:
            csv_rows.extend([{title[i]:row[title[i]] for i in range(len(title))}])

我试图在选择菜单中填充字段名称。但我无法弄清楚如何让用户:

  1. 从选择菜单中选择要更新的字段名称。
  2. 输入新字段名称。
  3. 点击“更新”按钮更改字段名称。
  4. HTML

    <div class="container">
        <form class="col s12" action="/upload" method="POST" enctype="multipart/form-data">
        <div class="row">
            <div class="input-field col s12 m6">
                 <label>Update Fieldnames</label>
                    <select class="icons">
                    {% for x in title %}
                    <option value="{{ x }}"{% if loop.first %} SELECTED{% endif %}>{{ x }}</option>
                    {% endfor %}
                    </select>
                    <button class="btn" type="submit" value="Update">Submit</button>
            </div>
        </div>
        </form>
    </div>
    

1 个答案:

答案 0 :(得分:1)

模板

如前面的评论所述,您应该使用label和文本input(在html模板中)列表替换选择菜单。这使得该过程对您而言更加容易,并且主要针对用户,他们可以更新所有字段,而不是逐个编辑它们。

文本输入可以通过包含循环索引的名称来标识,因此您可以匹配POST请求中的原始字段(即使两个字段名相等)。默认值是原始标题,因此用户可以保留或修改。

显示示例:

Field 1 : Title1
Field 2 : Title2
<div class="container">
    <form class="col s12" action="/update" method="POST" enctype="multipart/form-data">
        <div class="row">
            <h2>Update Fieldnames</h2>
                {% for x in title %}
                  <label> Field {{ loop.index }} : </label>
                  <input type="text" name="field-{{ loop.index }}" value="{{ x }}" ></input>
                  <br>
                {% endfor %}
            <input type="hidden" name="filename" value= {{filename}}></input>
            <button class="btn" type="submit" value="Update">Submit</button>
        </div>
    </form>
</div>

文件名在表单中添加为隐藏输入,以便能够访问视图中的文件,并处理字段更新。

这需要在render_template语句中添加变量:

return render_template('main.html', title=data, filename=savepath) #according to the variable in the function save_in()

视图

然后update视图可以获取request.form值并创建新的字段名列表。

@app.route("/update", methods=['POST'])
def update():
    filepath = request.form['filename']
    newtitles = []
    for index in range(1, len(request.form)):  # begin at 1 and leave filename out
        newtitles.append(request.form.get('field-' + str(index)))

    rows = [newtitles] # stores the new header

    with open(filepath, 'r') as csv_in :
        reader = csv.reader(csv_in)
        next(reader, None) # ignores the original header
        for row in reader:
            rows.append(row) # stores all rows

    with open(filepath, 'w') as csv_out:
        writer = csv.writer(csv_out)
        writer.writerows(rows) # writes all rows, including new header

    return """<html><div>New titles updated: {} to the file {}</div></html>""".format(newtitles, filepath)

该文件被新版本取代,实现此目的需要更多行,但如果您希望保留原始版本,则可以从this post获得灵感。