13

I'm using Python 2.7 and Django 1.7.

I have a method in my admin interface that generates some kind of a csv file.

def generate_csv(args):
    ...
    #some code that generates a dictionary to be written as csv
    ....

    # this creates a directory and returns its filepath
    dirname = create_csv_dir('stock')

    csvpath = os.path.join(dirname, 'mycsv_file.csv')
    fieldnames = [#some field names]

    # this function creates the csv file in the directory shown by the csvpath
    newcsv(data, csvheader, csvpath, fieldnames)

    # this automatically starts a download from that directory
    return HttpResponseRedirect('/media/csv/stock/%s' % csvfile)

All in all I create a csv file, save it somewhere on the disk, and then pass its URL to the user for download.

I was thinking if all this can be done without writing to disc. I googled around a bit and maybe content disposition attachment might help me, but I got lost in documentation a bit.

Anyway if there's an easier way of doing this I'd love to know.

Saša Kalaba
  • 4,241
  • 6
  • 29
  • 52
  • Look into `StringIO` – Cody Bouche Sep 17 '15 at 15:42
  • 1
    Looks like this is very similar to the question here as it pretty much the same thing, just different payloads: http://stackoverflow.com/questions/908258/generating-file-to-download-with-django – Ragora Sep 17 '15 at 15:46

2 Answers2

13

Thanks to @Ragora, you pointed me towards the right direction.

I rewrote the newcsv method:

from io import StringIO
import csv


def newcsv(data, csvheader, fieldnames):
    """
    Create a new csv file that represents generated data.
    """
    new_csvfile = StringIO.StringIO()
    wr = csv.writer(new_csvfile, quoting=csv.QUOTE_ALL)
    wr.writerow(csvheader)
    wr = csv.DictWriter(new_csvfile, fieldnames = fieldnames)

    for key in data.keys():
        wr.writerow(data[key])

    return new_csvfile

and in the admin:

csvfile = newcsv(data, csvheader, fieldnames)

response = HttpResponse(csvfile.getvalue(), content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename=stock.csv'
return response
Preston Badeer
  • 2,658
  • 1
  • 20
  • 21
Saša Kalaba
  • 4,241
  • 6
  • 29
  • 52
-2

If it annoys you that you are saving a file to disk, just add the application/octet-stream content-type to the Content-Disposition header then delete the file from disk.

If this header (Content-Disposition) is used in a response with the application/octet- stream content-type, the implied suggestion is that the user agent should not display the response, but directly enter a `save response as...' dialog.

Ólafur Aron
  • 352
  • 2
  • 12