Dropzone.js 阻止 Flask 渲染模板。

13

我正在使用Dropzone.js实现通过Flask网站进行拖放上传CSV文件的功能。上传过程很顺利,我将上传的文件保存到指定的文件夹中,然后可以使用df.to_html()dataframe转换为HTML代码,并将其传递给我的模板。它能够执行到这个代码段,但不会渲染模板,也不会抛出任何错误。所以我的问题是,为什么Dropzone.js会阻止渲染?

我还尝试过直接返回表格的HTML代码而不使用render_template,但这也没有起作用。

init.py

import os
from flask import Flask, render_template, request
import pandas as pd

app = Flask(__name__)

# get the current folder
APP_ROOT = os.path.dirname(os.path.abspath(__file__))

@app.route('/')
def index():
    return render_template('upload1.html')


@app.route('/upload', methods=['POST'])
def upload():

    # set the target save path
    target = os.path.join(APP_ROOT, 'uploads/')

    # loop over files since we allow multiple files
    for file in request.files.getlist("file"):

        # get the filename
        filename = file.filename

        # combine filename and path
        destination = "/".join([target, filename])

        # save the file
        file.save(destination)

        #upload the file
        df = pd.read_csv(destination)
        table += df.to_html()

    return render_template('complete.html', table=table)


if __name__ == '__main__':
    app.run(port=4555, debug=True)

上传1文件.html

<!DOCTYPE html>

<meta charset="utf-8">

<script src="https://rawgit.com/enyo/dropzone/master/dist/dropzone.js"></script>
<link rel="stylesheet" href="https://rawgit.com/enyo/dropzone/master/dist/dropzone.css">


<table width="500">
    <tr>
        <td>
            <form action="{{ url_for('upload') }}", method="POST" class="dropzone"></form>
        </td>
    </tr>
</table>

编辑

这是我正在上传的csv数据示例:

Person,Count
A,10
B,12
C,13

完成.html

<html>

<body>

{{table | safe }}

</body>
</html>

complete.html 的内容是什么? - HassenPy
这实际上基本上只是通过 render_template 传递的表格的 HTML 代码。我已经将其添加到问题中了。 - user2242044
3个回答

10

更新:现在您可以使用Flask-Dropzone,这是一个将Dropzone.js与Flask集成的Flask扩展程序。对于此问题,您可以将DROPZONE_REDIRECT_VIEW设置为上传完成后要重定向的视图。


Dropzone.js使用AJAX来提交数据,因此它不会将控制权返回给您的视图函数。

有两种方法可以在所有文件上传完成后进行重定向(或呈现模板)。

  • 您可以添加一个按钮进行重定向。

    <a href="{{ url_for('upload') }}">上传完成</a>

  • 您可以添加一个事件侦听器以自动重定向页面(使用jQuery)。

    <script>
    Dropzone.autoDiscover = false;
    
    $(function() {
      var myDropzone = new Dropzone("#my-dropzone");
      myDropzone.on("queuecomplete", function(file) {
        // Called when all files in the queue finish uploading.
        window.location = "{{ url_for('upload') }}";
      });
    })
    </script>
    

    在视图函数中,添加一个 if 语句来检查 HTTP 方法是否为 POST:

在视图函数中,添加一个 if 语句来检查 HTTP 方法是否为 POST:

import os
from flask import Flask, render_template, request

app = Flask(__name__)
app.config['UPLOADED_PATH'] = 'the/path/to/upload'

@app.route('/')
def index():
    # render upload page
    return render_template('index.html')


@app.route('/upload', methods=['GET', 'POST'])
def upload():
    if request.method == 'POST':
        for f in request.files.getlist('file'):
            f.save(os.path.join('the/path/to/upload', f.filename))
    return render_template('your template to render')

5

您的代码可以正常工作。您的模板将被渲染并返回。

Dropzone将把您在浏览器中拖放的文件上传到后台。 它会使用来自服务器的响应并保留页面不变。它使用来自服务器的响应来确定上传是否成功。

要查看此过程,请执行以下操作:

  • 导航到您的页面
  • 打开您喜欢的浏览器开发工具(在Firefox中按CTRL+SHIFT+K)
  • 选择网络选项卡
  • 将CSV文件拖放到dropzone窗格中,注意请求显示在开发工具网络表中

这是我浏览器中的屏幕截图。我从您的问题中直接复制了您的代码。

代码正常工作的屏幕截图

要实际查看呈现的complete.html,您需要添加另一个flask端点并找到访问该端点的方法。

例如:在upload1.html中添加:

<a href="{{ url_for('upload_complete') }}">Click here when you have finished uploading</a>

init.py 文件中进行更改和添加:

def upload():

    ...

        # you do not need to read_csv in upload()
        #upload the file
        #df = pd.read_csv(destination)
        #table += df.to_html()

    return "OK"
    # simply returning HTTP 200 is enough for dropzone to treat it as successful
    # return render_template('complete.html', table=table)

# add the new upload_complete endpoint
# this is for example only, it is not suitable for production use
@app.route('/upload-complete')
def upload_complete():
    target = os.path.join(APP_ROOT, 'uploads/')
    table=""
    for file_name in os.listdir(target):
        df = pd.read_csv(file_name)
        table += df.to_html()
    return render_template('complete.html', table=table)

1
谢谢,非常好的答案。我最终添加了一个链接。没有自动渲染的方法吗? - user2242044

0
如果你正在使用 Flask-Dropzone, 那么:
{{ dropzone.config(redirect_url=url_for('endpoint',foo=bar)) }}

请完整提出您的问题以获得更好的答案。 - Ehsan Ali

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接