outputting-csv.txt 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. .. _howto-outputting-csv:
  2. ==========================
  3. Outputting CSV with Django
  4. ==========================
  5. This document explains how to output CSV (Comma Separated Values) dynamically
  6. using Django views. To do this, you can either use the `Python CSV library`_ or
  7. the Django template system.
  8. .. _Python CSV library: http://www.python.org/doc/current/lib/module-csv.html
  9. Using the Python CSV library
  10. ============================
  11. Python comes with a CSV library, ``csv``. The key to using it with Django is
  12. that the ``csv`` module's CSV-creation capability acts on file-like objects, and
  13. Django's :class:`~django.http.HttpResponse` objects are file-like objects.
  14. Here's an example::
  15. import csv
  16. from django.http import HttpResponse
  17. def some_view(request):
  18. # Create the HttpResponse object with the appropriate CSV header.
  19. response = HttpResponse(mimetype='text/csv')
  20. response['Content-Disposition'] = 'attachment; filename=somefilename.csv'
  21. writer = csv.writer(response)
  22. writer.writerow(['First row', 'Foo', 'Bar', 'Baz'])
  23. writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"])
  24. return response
  25. The code and comments should be self-explanatory, but a few things deserve a
  26. mention:
  27. * The response gets a special MIME type, ``text/csv``. This tells
  28. browsers that the document is a CSV file, rather than an HTML file. If
  29. you leave this off, browsers will probably interpret the output as HTML,
  30. which will result in ugly, scary gobbledygook in the browser window.
  31. * The response gets an additional ``Content-Disposition`` header, which
  32. contains the name of the CSV file. This filename is arbitrary; call it
  33. whatever you want. It'll be used by browsers in the "Save as..."
  34. dialogue, etc.
  35. * Hooking into the CSV-generation API is easy: Just pass ``response`` as the
  36. first argument to ``csv.writer``. The ``csv.writer`` function expects a
  37. file-like object, and :class:`~django.http.HttpResponse` objects fit the
  38. bill.
  39. * For each row in your CSV file, call ``writer.writerow``, passing it an
  40. iterable object such as a list or tuple.
  41. * The CSV module takes care of quoting for you, so you don't have to worry
  42. about escaping strings with quotes or commas in them. Just pass
  43. ``writerow()`` your raw strings, and it'll do the right thing.
  44. Using the template system
  45. =========================
  46. Alternatively, you can use the :ref:`Django template system <topics-templates>`
  47. to generate CSV. This is lower-level than using the convenient CSV, but the
  48. solution is presented here for completeness.
  49. The idea here is to pass a list of items to your template, and have the
  50. template output the commas in a :ttag:`for` loop.
  51. Here's an example, which generates the same CSV file as above::
  52. from django.http import HttpResponse
  53. from django.template import loader, Context
  54. def some_view(request):
  55. # Create the HttpResponse object with the appropriate CSV header.
  56. response = HttpResponse(mimetype='text/csv')
  57. response['Content-Disposition'] = 'attachment; filename=somefilename.csv'
  58. # The data is hard-coded here, but you could load it from a database or
  59. # some other source.
  60. csv_data = (
  61. ('First row', 'Foo', 'Bar', 'Baz'),
  62. ('Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"),
  63. )
  64. t = loader.get_template('my_template_name.txt')
  65. c = Context({
  66. 'data': csv_data,
  67. })
  68. response.write(t.render(c))
  69. return response
  70. The only difference between this example and the previous example is that this
  71. one uses template loading instead of the CSV module. The rest of the code --
  72. such as the ``mimetype='text/csv'`` -- is the same.
  73. Then, create the template ``my_template_name.txt``, with this template code:
  74. .. code-block:: html+django
  75. {% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
  76. {% endfor %}
  77. This template is quite basic. It just iterates over the given data and displays
  78. a line of CSV for each row. It uses the :tfilter:`addslashes` template filter to
  79. ensure there aren't any problems with quotes.
  80. Other text-based formats
  81. ========================
  82. Notice that there isn't very much specific to CSV here -- just the specific
  83. output format. You can use either of these techniques to output any text-based
  84. format you can dream of. You can also use a similar technique to generate
  85. arbitrary binary data; see :ref:`howto-outputting-pdf` for an example.