在cookiecutter-flask app中使用Flask-wtforms上传文件

Ali*_*n S 13 python flask flask-wtforms flask-uploads

我在将文件上传工作到cookiecutter-flask应用程序(v.10.1.1)时遇到问题.现在,它没有保存上传的文件.

Cookiecutter-Flask默认安装WTForms和Flask-WTForms.我已经尝试过添加Flask-Uploads,但我不相信模块在这一点上添加了任何东西,所以我已经卸载了它.这是Flask-WTF文件上传文档:http://flask-wtf.readthedocs.io/en/latest/form.html#module-flask_wtf.file

文档和我的应用程序之间的主要区别在于我似乎有更多文件的信息,符合cookiecutter的约定.

app_name/spreadsheet/forms.py:

from flask_wtf import Form
from wtforms.validators import DataRequired
from flask_wtf.file import FileField, FileAllowed, FileRequired

class UploadForm(Form):
    """Upload form."""

    csv = FileField('Your CSV', validators=[FileRequired(),FileAllowed(['csv', 'CSVs only!'])])

    def __init__(self, *args, **kwargs):
        """Create instance."""
        super(UploadForm, self).__init__(*args, **kwargs)
        self.user = None

    def validate(self):
        """Validate the form."""
        initial_validation = super(UploadForm, self).validate()
        if not initial_validation:
            return False
Run Code Online (Sandbox Code Playgroud)

app_name/spreadsheet/views.py:

from flask import Blueprint, render_template
from flask_login import login_required
from werkzeug.utils import secure_filename
from app_name.spreadsheet.forms import UploadForm
from app_name.spreadsheet.models import Spreadsheet
from app_name.utils import flash, flash_errors

blueprint = Blueprint('spreadsheet', __name__, url_prefix='/spreadsheets', static_folder='../static')

@blueprint.route('/upload', methods=['GET', 'POST']) #TODO test without GET since it won't work anyway
@login_required
def upload():
    uploadform = UploadForm()
    if uploadform.validate_on_submit():
        filename = secure_filename(form.csv.data.filename)
        uploadform.csv.data.save('uploads/csvs/' + filename)
        flash("CSV saved.")
        return redirect(url_for('list'))
    else:
        filename = None
    return render_template('spreadsheets/upload.html', uploadform=uploadform)
Run Code Online (Sandbox Code Playgroud)

这是命令行输出,当我上传文件时没有显示错误:

 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [04/Sep/2016 10:29:10] "GET /spreadsheets/upload HTTP/1.1" 200 -
127.0.0.1 - - [04/Sep/2016 10:29:10] "GET /_debug_toolbar/static/css/toolbar.css?0.3058158586562558 HTTP/1.1" 200 -
127.0.0.1 - - [04/Sep/2016 10:29:14] "POST /spreadsheets/upload HTTP/1.1" 200 -
127.0.0.1 - - [04/Sep/2016 10:29:14] "GET /_debug_toolbar/static/css/toolbar.css?0.3790246965220061 HTTP/1.1" 200 -
Run Code Online (Sandbox Code Playgroud)

对于uploads/csvs目录,我尝试了绝对和相对路径,并且目录被许可766.

模板文件是:

{% extends "layout.html" %}
{% block content %}
    <h1>Welcome {{ session.username }}</h1>

    {% with uploadform=uploadform  %}
        {% if current_user and current_user.is_authenticated and uploadform %}
            <form id="uploadForm" method="POST" class="" action="{{ url_for('spreadsheet.upload') }}" enctype="multipart/form-data">
              <input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
              <div class="form-group">
                {{ uploadform.csv(class_="form-control") }}
              </div>
              <button type="submit" class="btn btn-default">Upload</button>
            </form>
        {% endif %}
    {% endwith %}

{% endblock %}
Run Code Online (Sandbox Code Playgroud)

哪个生成这个HTML:

        <form id="uploadForm" method="POST" class="" action="/spreadsheets/upload" enctype="multipart/form-data">
          <input type="hidden" name="csrf_token" value="LONG_RANDOM_VALUE"/>
          <div class="form-group">
            <input class="form-control" id="csv" name="csv" type="file">
          </div>
          <button type="submit" class="btn btn-default">Upload</button>
        </form>
Run Code Online (Sandbox Code Playgroud)

kfb*_*kfb 1

查看文档,您提供的链接表明 的字段datacsv的实例werkzeug.datastructures.FileStorage。的文档FileStorage.save()表明:

如果目标是文件对象,您必须在调用后自行关闭它。

是否因为您没有关闭文件,所以它没有被写入磁盘?