2016-06-23 8 views
1

の読み方、私は単純にCSVライターを使用してCSVで完全に構成さDjangoのHttpResponseオブジェクトを作成:ユニットテストではビューでCSVジャンゴHTTPレスポンス

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?) 

私はresponse.contentは、文字列をバック吐き出していることはHttpResponseソースで見ます私はバイト文字列として、私は正しい方法を理解することができませんcsv.readerファイルを正しく読み取らせるには対処する。私は(あなたがオブジェクト自体に書き込みをするので、それはコンテンツだではない)だけresponseresponse.contentを置き換えることができるだろうと思ったが、それは単にエラーのわずかな変動が生じた:

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

明らかに近いが、そうですまだ間違っています。 csvドキュメントを読むと、ファイルを正しく開くことができないと思います。 csv.readerがそれを解析できるように、このファイルのようなオブジェクトを「開く」方法は?

答えて

3

response.contentは、バイトを提供します。あなたは、文字列にこれをデコードする必要があります。

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

はその後io.StringIOを使用してCSVリーダーにこの文字列を渡す:

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

どちらの回答も有効ですが、私の特定のケースでは、内容が非常に小さいので、knbkの答えによって得られるマイナーなパフォーマンスの向上がこの回答の読みやすさを上回っています。どちらも受け入れられました。私が最後に使用した形式は次のとおりです: 'reader = csv.reader(StringIO(response.content.decode( 'utf-8')))'。 – fildred13

2

あなたはテキストストリームに提供されるバイト文字列を変換するためにio.TextIOWrapperを使用することができます。

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

これは、読み込み中にバイトを文字列に変換します。

+0

私の 'reader ='行をあなたのものに置き換えると、エラーが出ます: 'AttributeError: 'bytes'オブジェクトには属性 'readable'がありません。調査中... – fildred13

+0

私の初期のコメントをさらに調査したところ、間違っていました。これを使うには、まずBytesIOに 'response.content'を渡す必要があります。 – miyamoto

+2

あなたはそれについて正しいです。一度にすべてのコンテンツではなく、チャンクをデコードするという利点がありますが、一般的には違いはありません。ほとんどの場合、あなたの答えは使いやすくなりますが、ここでは完全にするためにこのままにしておきます。 – knbk

関連する問題