最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Dropzone.js prevents Flask from rendering template - Stack Overflow

programmeradmin0浏览0评论

I am using Dropzone.js to allow drag and drop upload of CSV files via a Flask web site. The upload process works great. I save the uploaded file to my specified folder and can then use df.to_html() to convert the dataframe into HTML code, which I then pass to my template. It gets to that point in the code, but it doesn't render the template and no errors are thrown. So my question is why is Dropzone.js preventing the render from happening?

I have also tried just return the HTML code from the table and not using render_template, but this also does not work.

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)

upload1.html

<!DOCTYPE html>

<meta charset="utf-8">

<script src=".js"></script>
<link rel="stylesheet" href=".css">


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

EDIT

Here is the sample csv data I am uploading:

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

Complete.html

<html>

<body>

{{table | safe }}

</body>
</html>

I am using Dropzone.js to allow drag and drop upload of CSV files via a Flask web site. The upload process works great. I save the uploaded file to my specified folder and can then use df.to_html() to convert the dataframe into HTML code, which I then pass to my template. It gets to that point in the code, but it doesn't render the template and no errors are thrown. So my question is why is Dropzone.js preventing the render from happening?

I have also tried just return the HTML code from the table and not using render_template, but this also does not work.

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)

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

EDIT

Here is the sample csv data I am uploading:

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

Complete.html

<html>

<body>

{{table | safe }}

</body>
</html>
Share Improve this question edited Feb 10, 2017 at 19:41 user2242044 asked Feb 7, 2017 at 23:15 user2242044user2242044 9,21329 gold badges104 silver badges171 bronze badges 2
  • what's the content for complete.html? – HassenPy Commented Feb 10, 2017 at 19:32
  • It's really basically just the html code for the table passed via render_template. I've added it the question. – user2242044 Commented Feb 10, 2017 at 19:42
Add a comment  | 

3 Answers 3

Reset to default 10 +100

Update: Now you can use Flask-Dropzone, a Flask extension that integrates Dropzone.js with Flask. For this issue, you can set DROPZONE_REDIRECT_VIEW to the view you want to redirect when uploading complete.


Dropzone.js use AJAX to post data, that's why it will not give back the control to your view function.

There are two methods to redirect (or render template) when all files were complete uploading.

  • You can add a button to redirect.

    <a href="{{ url_for('upload') }}">Upload Complete</a>

  • You can add an event listener to automatic redirect page (use 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>
    

In view function, add an if statement to check whether the HTTP method was 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')

Your code does work. Your template will be rendered and returned.

Dropzone will upload files you drag and drop into your browser 'in the background'. It will consume the response from the server and leave the page as is. It uses the response from the server to know if the upload was successful.

To see this in action:

  • Navigate to your page
  • Open up your favourite browser dev tools; (in firefox press CTRL+SHIFT+K)
  • Select the network tab
  • Drag your csv into the dropzone pane and note that the request shows in the dev tools network table

Here is a screen shot from my browser. I copied your code as is from your question.

To actually see the rendered complete.html you will need to add another flask endpoint and have a way to navigate to that.

For example: in upload1.html add:

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

in init.py change and add:

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)

If you are using Flask-Dropzone then:

{{ dropzone.config(redirect_url=url_for('endpoint',foo=bar)) }}
发布评论

评论列表(0)

  1. 暂无评论