1

I have created a Flask app that creates a list and returns the list to an HTML page. I would also like to make the list downloadable as a CSV file.

So far I understand how to do these tasks as separate functions.

Is there a way to combine these functions into one so that a list is created only once, displaying the data on an HTML template, and also providing a download link?

Please view the basic examples below:

from flask import Flask, render_template, Response, url_for

app = Flask(__name__)

@app.route('/')
def hello_world():
    fruits = ['apple', 'pear', 'banana', 'grapes', 'mango']
    return render_template('fruit.html', fruit=fruits)


@app.route('/fruits.csv')
def generate_fruit_file():
    def generate():
        fruits = ['apple', 'pear', 'banana', 'grapes', 'mango']
        for f in fruits:
            yield ''.join(f) + '\n'
    return Response(generate(), mimetype='text/csv')


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

HTML template:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
{% for f in fruit %}
    <ul>
        <li style="display: block;">{{ f }}</li>
    </ul>
{% endfor %}
    <a href="{{'/fruits.csv'}}">get file</a>
</body>
</html>
gandreadis
  • 3,004
  • 2
  • 26
  • 38
user50083
  • 77
  • 2
  • 8
  • I believe your question lacks a bit of context. When you say that your application generates a list of things, that implies the list is generated from some data. Where is that data stored? – Born2Discover Jan 03 '17 at 13:01
  • you can refer http://stackoverflow.com/questions/24577349/flask-download-a-file – SunilThorat Jan 03 '17 at 13:05
  • Born2Discover: The data is created from an API call and stored onto a database. In my main project I use a generator function to collect the data. I then store the output of the generator to a list object before saving it to the database and displaying it on the template. – user50083 Jan 03 '17 at 14:40

1 Answers1

0

The simplest way is to define a global variable fruits in your module that you access from each function.

fruits = ['apple', 'pear', 'banana', 'grapes', 'mango']

@app.route('/')
def hello_world():
    global fruits
    return render_template('fruit.html', fruit=fruits)


@app.route('/fruits.csv')
def generate_fruit_file():
    def generate():
        global fruits
        for f in fruits:
            yield ''.join(f) + '\n'
    return Response(generate(), mimetype='text/csv')
MrLeeh
  • 5,321
  • 6
  • 33
  • 51
  • I initially tried this. It works great in debug mode but not in production. Maybe using flask.g is an option? – user50083 Jan 03 '17 at 14:41
  • That is strange. What error are you getting? `Flask.g` won't work as it only stores values during one request. In your case you have two separate requests: one request to display your html file and one to download the csv. – MrLeeh Jan 03 '17 at 14:49
  • Bear in mind the code I submitted was a resemblance to the project I am working on. The function that collects the data and generates the list can easily send the data to a global variable. I have an issue with returning that data from another function. The data is gone by the time the file output function can collect it resulting in empty files. – user50083 Jan 04 '17 at 15:47
  • I might be missing something but If you store your data in a global list it will be accessible from all function as long as your server runs. The data can not be just gone. – MrLeeh Jan 04 '17 at 15:54
  • I have found that I can print the contents of the list from within the first function. If I try the same for the function to create the file, it returns an empty list. I agree with you that the data should still be in that list but it seems as though the second function can not access it properly if at all. – user50083 Jan 04 '17 at 16:29
  • Came back to say it does indeed work and it did not before due to my own error. – user50083 Jan 06 '17 at 13:23