2016-09-04 15 views
12

Tôi gặp sự cố khi tải tệp lên để hoạt động trong ứng dụng cookiecutter-flask (v. 0.10.1). Ngay bây giờ, nó không lưu tập tin được tải lên.Tệp không tải lên bằng Flask-wtforms trong ứng dụng cookiecutter-flask

Cookiecutter-Flask theo cài đặt mặc định WTForms và Flask-WTForms. Tôi đã thử thêm Flask-Uploads vào điều này nhưng tôi không tin rằng module thêm bất cứ điều gì vào thời điểm này vì vậy tôi đã gỡ cài đặt nó. Đây là tài liệu tải lên tệp Flask-WTF: http://flask-wtf.readthedocs.io/en/latest/form.html#module-flask_wtf.file

Sự khác biệt chính giữa tài liệu và ứng dụng của tôi là dường như tôi có thông tin trong nhiều tệp hơn, phù hợp với các quy ước của cookiecutter.

Trong 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 

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

Đây là sản phẩm dòng lệnh cho thấy không có lỗi khi tôi tải lên một tập tin:

* 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 - 

Đối với thư mục uploads/csvs Tôi đã thử các đường dẫn tuyệt đối và tương đối và thư mục là được cấp quyền 766.

Mẫu tập tin là:

{% 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 %} 

nào tạo ra HTML này:

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

Trả lời

0

Nhìn qua các tài liệu, liên kết mà bạn cung cấp cho thấy rằng data lĩnh vực csv là một thể hiện của werkzeug.datastructures.FileStorage. Tài liệu cho số FileStorage.save() gợi ý rằng:

Nếu đích là đối tượng tệp bạn phải tự đóng sau cuộc gọi.

Có thể vì bạn không đóng tệp, nó không được ghi vào đĩa?

0

Hãy thử điều này:

from flask import request 

if uploadform.validate_on_submit(): 
    if 'csv' in request.files: 
     csv = request.files['csv'] 
     csv.save('uploads/csvs/' + csv.filename) 
0

Nguyên nhân chủ yếu của vấn đề đất đai của bạn ở đây:

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

như vậy trong validate phương pháp UploadForm lớp.

Hãy nhanh chóng điều tra những gì đang xảy ra ở đây.

Trong views.py phù hợp:

if uploadform.validate_on_submit(): 

flask_wtf gói gọi validate phương pháp.Vì vậy, hãy xem lại phương pháp ghi đè của bạn:

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

điều gì sai ở đây? Trong trường hợp initial_validation sẽ là True, phương pháp validate của bạn sẽ trả lại None. Vậy điều gì sẽ xảy ra? Chỉ html rendering:

def upload(): 
    uploadform = UploadForm() 
    if uploadform.validate_on_submit(): # <--- here it's None 
     filename = secure_filename(form.csv.data.filename) 
     uploadform.csv.data.save('uploads/csvs/' + filename) 
     flash("CSV saved.") 
     return redirect(url_for('list')) 
    else:        # <--- so this block runs 
     filename = None 
    # And your app will only render the same view as when using HTTP GET on that method 
    return render_template('spreadsheets/upload.html', uploadform=uploadform) 

Vì vậy, nếu ghi đè validate phương pháp là không cần thiết, sau đó chỉ cần loại bỏ nó, và nếu là, sau đó điều chỉnh nó để trở về True:

def validate(self): 
    """Validate the form.""" 
    initial_validation = super(UploadForm, self).validate() 
    if not initial_validation: 
     return False 
    return True # <-- this part is missing 

Tất nhiên bạn có thể sử dụng rút ngắn và Tôi nghĩ rằng phiên bản phù hợp hơn:

def validate(self): 
    """Validate the form.""" 
    initial_validation = super(UploadForm, self).validate() 
    return not initial_validation 
Các vấn đề liên quan