parts/django/docs/howto/outputting-csv.txt
changeset 69 c6bca38c1cbf
equal deleted inserted replaced
68:5ff1fc726848 69:c6bca38c1cbf
       
     1 ==========================
       
     2 Outputting CSV with Django
       
     3 ==========================
       
     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 
       
     9 .. _Python CSV library: http://docs.python.org/library/csv.html
       
    10 
       
    11 Using the Python CSV library
       
    12 ============================
       
    13 
       
    14 Python comes with a CSV library, ``csv``. The key to using it with Django is
       
    15 that the ``csv`` module's CSV-creation capability acts on file-like objects, and
       
    16 Django's :class:`~django.http.HttpResponse` objects are file-like objects.
       
    17 
       
    18 Here's an example::
       
    19 
       
    20     import csv
       
    21     from django.http import HttpResponse
       
    22 
       
    23     def some_view(request):
       
    24         # Create the HttpResponse object with the appropriate CSV header.
       
    25         response = HttpResponse(mimetype='text/csv')
       
    26         response['Content-Disposition'] = 'attachment; filename=somefilename.csv'
       
    27 
       
    28         writer = csv.writer(response)
       
    29         writer.writerow(['First row', 'Foo', 'Bar', 'Baz'])
       
    30         writer.writerow(['Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"])
       
    31 
       
    32         return response
       
    33 
       
    34 The code and comments should be self-explanatory, but a few things deserve a
       
    35 mention:
       
    36 
       
    37     * The response gets a special MIME type, ``text/csv``. This tells
       
    38       browsers that the document is a CSV file, rather than an HTML file. If
       
    39       you leave this off, browsers will probably interpret the output as HTML,
       
    40       which will result in ugly, scary gobbledygook in the browser window.
       
    41 
       
    42     * The response gets an additional ``Content-Disposition`` header, which
       
    43       contains the name of the CSV file. This filename is arbitrary; call it
       
    44       whatever you want. It'll be used by browsers in the "Save as..."
       
    45       dialogue, etc.
       
    46 
       
    47     * Hooking into the CSV-generation API is easy: Just pass ``response`` as the
       
    48       first argument to ``csv.writer``. The ``csv.writer`` function expects a
       
    49       file-like object, and :class:`~django.http.HttpResponse` objects fit the
       
    50       bill.
       
    51 
       
    52     * For each row in your CSV file, call ``writer.writerow``, passing it an
       
    53       iterable object such as a list or tuple.
       
    54 
       
    55     * The CSV module takes care of quoting for you, so you don't have to worry
       
    56       about escaping strings with quotes or commas in them. Just pass
       
    57       ``writerow()`` your raw strings, and it'll do the right thing.
       
    58 
       
    59 Handling Unicode
       
    60 ~~~~~~~~~~~~~~~~
       
    61 
       
    62 Python's ``csv`` module does not support Unicode input. Since Django uses
       
    63 Unicode internally this means strings read from sources such as
       
    64 :class:`~django.http.HttpRequest` are potentially problematic. There are a few
       
    65 options for handling this:
       
    66 
       
    67     * Manually encode all Unicode objects to a compatible encoding.
       
    68 
       
    69     * Use the ``UnicodeWriter`` class provided in the `csv module's examples
       
    70       section`_.
       
    71 
       
    72     * Use the `python-unicodecsv module`_, which aims to be a drop-in
       
    73       replacement for ``csv`` that gracefully handles Unicode.
       
    74 
       
    75 For more information, see the Python `CSV File Reading and Writing`_
       
    76 documentation.
       
    77 
       
    78 .. _`csv module's examples section`: http://docs.python.org/library/csv.html#examples
       
    79 .. _`python-unicodecsv module`: https://github.com/jdunck/python-unicodecsv
       
    80 .. _`CSV File Reading and Writing`: http://docs.python.org/library/csv.html
       
    81 
       
    82 Using the template system
       
    83 =========================
       
    84 
       
    85 Alternatively, you can use the :doc:`Django template system </topics/templates>`
       
    86 to generate CSV. This is lower-level than using the convenient Python ``csv``
       
    87 module, but the solution is presented here for completeness.
       
    88 
       
    89 The idea here is to pass a list of items to your template, and have the
       
    90 template output the commas in a :ttag:`for` loop.
       
    91 
       
    92 Here's an example, which generates the same CSV file as above::
       
    93 
       
    94     from django.http import HttpResponse
       
    95     from django.template import loader, Context
       
    96 
       
    97     def some_view(request):
       
    98         # Create the HttpResponse object with the appropriate CSV header.
       
    99         response = HttpResponse(mimetype='text/csv')
       
   100         response['Content-Disposition'] = 'attachment; filename=somefilename.csv'
       
   101 
       
   102         # The data is hard-coded here, but you could load it from a database or
       
   103         # some other source.
       
   104         csv_data = (
       
   105             ('First row', 'Foo', 'Bar', 'Baz'),
       
   106             ('Second row', 'A', 'B', 'C', '"Testing"', "Here's a quote"),
       
   107         )
       
   108 
       
   109         t = loader.get_template('my_template_name.txt')
       
   110         c = Context({
       
   111             'data': csv_data,
       
   112         })
       
   113         response.write(t.render(c))
       
   114         return response
       
   115 
       
   116 The only difference between this example and the previous example is that this
       
   117 one uses template loading instead of the CSV module. The rest of the code --
       
   118 such as the ``mimetype='text/csv'`` -- is the same.
       
   119 
       
   120 Then, create the template ``my_template_name.txt``, with this template code:
       
   121 
       
   122 .. code-block:: html+django
       
   123 
       
   124     {% for row in data %}"{{ row.0|addslashes }}", "{{ row.1|addslashes }}", "{{ row.2|addslashes }}", "{{ row.3|addslashes }}", "{{ row.4|addslashes }}"
       
   125     {% endfor %}
       
   126 
       
   127 This template is quite basic. It just iterates over the given data and displays
       
   128 a line of CSV for each row. It uses the :tfilter:`addslashes` template filter to
       
   129 ensure there aren't any problems with quotes.
       
   130 
       
   131 Other text-based formats
       
   132 ========================
       
   133 
       
   134 Notice that there isn't very much specific to CSV here -- just the specific
       
   135 output format. You can use either of these techniques to output any text-based
       
   136 format you can dream of. You can also use a similar technique to generate
       
   137 arbitrary binary data; see :doc:`/howto/outputting-pdf` for an example.