我正在尝试构建一个应用程序,它使用不同数量的列来获取不同的CSV文件。例如,我的CSV文件有大约30列,其字段名称具有特殊字符。所以,我想更新用户给出的字段名称。我有一个看起来像这样的CSV文件:
ques.1,ques.2
3,5
5,1
我想用用户(电视,广播)提供的标题更新列名ques.1, ques.2
。
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))}])
我试图在选择菜单中填充字段名称。但我无法弄清楚如何让用户:
<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>
答案 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获得灵感。