1Streaming Contents
2==================
3
4Sometimes you want to send an enormous amount of data to the client, much
5more than you want to keep in memory.  When you are generating the data on
6the fly though, how do you send that back to the client without the
7roundtrip to the filesystem?
8
9The answer is by using generators and direct responses.
10
11Basic Usage
12-----------
13
14This is a basic view function that generates a lot of CSV data on the fly.
15The trick is to have an inner function that uses a generator to generate
16data and to then invoke that function and pass it to a response object::
17
18    @app.route('/large.csv')
19    def generate_large_csv():
20        def generate():
21            for row in iter_all_rows():
22                yield f"{','.join(row)}\n"
23        return app.response_class(generate(), mimetype='text/csv')
24
25Each ``yield`` expression is directly sent to the browser.  Note though
26that some WSGI middlewares might break streaming, so be careful there in
27debug environments with profilers and other things you might have enabled.
28
29Streaming from Templates
30------------------------
31
32The Jinja2 template engine also supports rendering templates piece by
33piece.  This functionality is not directly exposed by Flask because it is
34quite uncommon, but you can easily do it yourself::
35
36    def stream_template(template_name, **context):
37        app.update_template_context(context)
38        t = app.jinja_env.get_template(template_name)
39        rv = t.stream(context)
40        rv.enable_buffering(5)
41        return rv
42
43    @app.route('/my-large-page.html')
44    def render_large_template():
45        rows = iter_all_rows()
46        return app.response_class(stream_template('the_template.html', rows=rows))
47
48The trick here is to get the template object from the Jinja2 environment
49on the application and to call :meth:`~jinja2.Template.stream` instead of
50:meth:`~jinja2.Template.render` which returns a stream object instead of a
51string.  Since we're bypassing the Flask template render functions and
52using the template object itself we have to make sure to update the render
53context ourselves by calling :meth:`~flask.Flask.update_template_context`.
54The template is then evaluated as the stream is iterated over.  Since each
55time you do a yield the server will flush the content to the client you
56might want to buffer up a few items in the template which you can do with
57``rv.enable_buffering(size)``.  ``5`` is a sane default.
58
59Streaming with Context
60----------------------
61
62.. versionadded:: 0.9
63
64Note that when you stream data, the request context is already gone the
65moment the function executes.  Flask 0.9 provides you with a helper that
66can keep the request context around during the execution of the
67generator::
68
69    from flask import stream_with_context, request
70
71    @app.route('/stream')
72    def streamed_response():
73        def generate():
74            yield 'Hello '
75            yield request.args['name']
76            yield '!'
77        return app.response_class(stream_with_context(generate()))
78
79Without the :func:`~flask.stream_with_context` function you would get a
80:class:`RuntimeError` at that point.
81