You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
116 lines
4.6 KiB
116 lines
4.6 KiB
.. _howto-outputting-csv: |
|
|
|
========================== |
|
Outputting CSV with Django |
|
========================== |
|
|
|
This document explains how to output CSV (Comma Separated Values) dynamically |
|
using Django views. To do this, you can either use the `Python CSV library`_ or |
|
the Django template system. |
|
|
|
.. _Python CSV library: http://www.python.org/doc/current/lib/module-csv.html |
|
|
|
Using the Python CSV library |
|
============================ |
|
|
|
Python comes with a CSV library, ``csv``. The key to using it with Django is |
|
that the ``csv`` module's CSV-creation capability acts on file-like objects, and |
|
Django's :class:`~django.http.HttpResponse` objects are file-like objects. |
|
|
|
Here's an example:: |
|
|
|
import csv |
|
from django.http import HttpResponse |
|
|
|
def some_view(request): |
|
# Create the HttpResponse object with the appropriate CSV header. |
|
response = HttpResponse(mimetype='text/csv') |
|
response['Content-Disposition'] = 'attachment; filename=somefilename.csv' |
|
|
|
writer = csv.writer(response) |
|
writer.writerow(['First row', 'Foo', 'Bar', 'Baz']) |
|
writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"]) |
|
|
|
return response |
|
|
|
The code and comments should be self-explanatory, but a few things deserve a |
|
mention: |
|
|
|
* The response gets a special MIME type, ``text/csv``. This tells |
|
browsers that the document is a CSV file, rather than an HTML file. If |
|
you leave this off, browsers will probably interpret the output as HTML, |
|
which will result in ugly, scary gobbledygook in the browser window. |
|
|
|
* The response gets an additional ``Content-Disposition`` header, which |
|
contains the name of the CSV file. This filename is arbitrary; call it |
|
whatever you want. It'll be used by browsers in the "Save as..." |
|
dialogue, etc. |
|
|
|
* Hooking into the CSV-generation API is easy: Just pass ``response`` as the |
|
first argument to ``csv.writer``. The ``csv.writer`` function expects a |
|
file-like object, and :class:`~django.http.HttpResponse` objects fit the |
|
bill. |
|
|
|
* For each row in your CSV file, call ``writer.writerow``, passing it an |
|
iterable object such as a list or tuple. |
|
|
|
* The CSV module takes care of quoting for you, so you don't have to worry |
|
about escaping strings with quotes or commas in them. Just pass |
|
``writerow()`` your raw strings, and it'll do the right thing. |
|
|
|
Using the template system |
|
========================= |
|
|
|
Alternatively, you can use the :ref:`Django template system <topics-templates>` |
|
to generate CSV. This is lower-level than using the convenient CSV, but the |
|
solution is presented here for completeness. |
|
|
|
The idea here is to pass a list of items to your template, and have the |
|
template output the commas in a :ttag:`for` loop. |
|
|
|
Here's an example, which generates the same CSV file as above:: |
|
|
|
from django.http import HttpResponse |
|
from django.template import loader, Context |
|
|
|
def some_view(request): |
|
# Create the HttpResponse object with the appropriate CSV header. |
|
response = HttpResponse(mimetype='text/csv') |
|
response['Content-Disposition'] = 'attachment; filename=somefilename.csv' |
|
|
|
# The data is hard-coded here, but you could load it from a database or |
|
# some other source. |
|
csv_data = ( |
|
('First row', 'Foo', 'Bar', 'Baz'), |
|
('Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"), |
|
) |
|
|
|
t = loader.get_template('my_template_name.txt') |
|
c = Context({ |
|
'data': csv_data, |
|
}) |
|
response.write(t.render(c)) |
|
return response |
|
|
|
The only difference between this example and the previous example is that this |
|
one uses template loading instead of the CSV module. The rest of the code -- |
|
such as the ``mimetype='text/csv'`` -- is the same. |
|
|
|
Then, create the template ``my_template_name.txt``, with this template code: |
|
|
|
.. code-block:: html+django |
|
|
|
{% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}" |
|
{% endfor %} |
|
|
|
This template is quite basic. It just iterates over the given data and displays |
|
a line of CSV for each row. It uses the :tfilter:`addslashes` template filter to |
|
ensure there aren't any problems with quotes. |
|
|
|
Other text-based formats |
|
======================== |
|
|
|
Notice that there isn't very much specific to CSV here -- just the specific |
|
output format. You can use either of these techniques to output any text-based |
|
format you can dream of. You can also use a similar technique to generate |
|
arbitrary binary data; see :ref:`howto-outputting-pdf` for an example.
|
|
|