【问题标题】:How to update the fieldnames of a csv file given by user input?如何更新用户输入给出的 csv 文件的字段名?
【发布时间】:2017-09-06 20:51:43
【问题描述】:

我正在尝试构建一个应用程序,它采用具有不同列数的不同 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. 单击“更新”按钮更改字段名称。

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>

【问题讨论】:

  • 我认为你有更好的选择来绘制标签(字段名称)和文本输入(新字段名称),而不是选择部分,它会更容易处理,也更方便为用户
  • 我将使用具有不同列数的不同 CSV 文件,因此,我不确定需要多少标签和文本输入。我认为提供一个选择菜单会是一个更好的主意,并且每次都更新它。
  • for 循环中,您可以在一行中绘制一个标签和一个输入,就像您为选择菜单的一个选项所做的那样。也许您有更简单的想法从用户那里获得新标题?
  • 你能告诉我一个例子来说明如何做到这一点,在得到文本输入后如何处理它?
  • 嗨@PRMoureu 由于一些健康问题,我无法试用您之前发布的代码。如果您能重新发布代码,将不胜感激?

标签: python html csv flask jinja2


【解决方案1】:

模板

正如之前在 cmets 中所说,您应该将选择菜单替换为 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获得一些灵感。

【讨论】:

  • return render_template('main.html', title=data, filename=savepath)
  • 谢谢。它对我来说非常有用。'for index in range(1, len(request.form)): newtitles.append(request.form.get('field-' + str(index)))' 这两行确实不适合我,所以我发现了字段的数量--for index in range(1, numofField+1): newtitles.append(request.form['field-' + str(index)])
  • 如何对我输入的名称应用表单验证。我希望 的名称长度为 8 且没有特殊字符?
  • 您好,您可以从这个post 测试函数中的特殊字符,并在标签&lt;input type="text" maxlength="8"... 内应用maxlength="8"
  • 请注意,这仅适用于按键,如果您想防止复制粘贴的禁用字符,您可能需要在视图中进行检查。下一步可能是使用带有验证器的 WTF 表单
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多