如何阅读csv django http响应

时间:2016-06-23 22:58:03

标签: python django csv

在视图中,我使用简单的csv编写器创建一个完全由csv组成的Django HttpResponse对象:

response = HttpResponse(content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="foobar.csv"'

writer = csv.writer(response)

    table_headers = ['Foo', 'Bar']
    writer.writerow(table_headers)

    bunch_of_rows = [['foo', 'bar'], ['foo2', 'bar2']]
    for row in bunch_of_rows:
        writer.writerow(row)

return response

在单元测试中,我想测试这个csv的某些方面,所以我需要阅读它。我试图这样做:

response = views.myview(args)

reader = csv.reader(response.content)

headers = next(reader)
row_count = 1 + sum(1 for row in reader)

self.assertEqual(row_count, 3) # header + 1 row for each attempt
self.assertIn('Foo', headers)

但测试失败,headers = next(reader)行上有以下内容:

nose.proxy.Error: iterator should return strings, not int (did you open the file in text mode?)

我在HttpResponse源代码中看到response.content正在将字符串作为字节字符串向外吐出,但我不确定正确处理这个问题的方法让csv.reader读取文件正确。我以为我可以用response.content替换response(因为你写的是对象本身,而不是它的内容),但这只会导致错误的轻微变化:

_csv.Error: iterator should return strings, not bytes (did you open the file in text mode?)

这似乎更接近但显然仍然是错误的。阅读csv文档,我假设我无法正确打开文件。我如何打开"这个类似文件的对象,以便csv.reader可以解析它?

2 个答案:

答案 0 :(得分:6)

response.content提供字节。您需要将其解码为字符串:

foo = response.content.decode('utf-8')

然后使用io.StringIO将此字符串传递给csv阅读器:

import io
reader = csv.reader(io.StringIO(foo))

答案 1 :(得分:2)

您可以使用io.TextIOWrapper将提供的字节字符串转换为文本流:

import io
reader = csv.reader(io.TextIOWrapper(io.BytesIO(response.content), encoding='utf-8'))

这会将字节转换为字符串,因为它们会被读者读取。