Django/Pytonを使ってCSVファイルをあれこれするために、いろいろ調べたので、その際の備忘録。
環境はDjango1.10.1とPython2.7
CSVファイルの扱いは、基本的にimport csv
のパッケージ
okadateさんのQiita記事にあるとおり、PythonでのCSVファイルの操作は以下な感じ。
import csv # 読み込み with open('some.csv', 'r') as f: reader = csv.reader(f) header = next(reader) # ヘッダーを読み飛ばしたい時 for row in reader: print row # 1行づつ取得できる # 書き込み with open('some.csv', 'w') as f: writer = csv.writer(f, lineterminator='\n') # 改行コード(\n)を指定しておく writer.writerow(list) # list(1次元配列)の場合 writer.writerows(array2d) # 2次元配列も書き込める
Django上でこれらを行うときは、リクエストとレスポンスも絡んでくる。
アップロードされたCSVファイルを読み込んで処理する
アップロードされたCSVファイルを読み込む場合は、open()
がrequest.FILES['file']
になる感じ。
import csv import traceback from django.shortcuts import render def upload_file(request): try: csv_file = request.FILES['file'] reader = csv.reader(req_file) header = next(reader) for csv_row in reader: print csv_row csv_file .close() except: traceback.format_exc() return render(request, "index.html")
CSVファイルをダウンロードする
基本的には、csv.writer
を使って、`responseに書き込んでいく感じ。
ただ、日本語の場合は、ファイル名とファイルの中身の文字コードに注意!!
import csv import urllib from django.http.response import HttpResponse def download_csv(request): filename = urllib.quote((u'CSVファイル.csv').encode("utf8")) response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename*=UTF-8\'\'{}'.format(filename) writer = csv.writer(response) writer.writerow(map(lambda n:toSJIS(n), [u'概要', u'詳細'])) writer.writerow(map(lambda n:toSJIS(n), [u'ああああ', u'いいい'])) writer.writerow(map(lambda n:toSJIS(n), [u'かかかか', u'ききき'])) return response def toSJIS(s=""): u'{}'.format(s).encode("sjis")
複数のCSVファイルをzipにまとめてダウンロードする
こちらも基本はcsv.writer
を使ってzip_file
に書き込み、zip_file
の内容をresponseに設定する感じ。
注意点はこちらも文字コード周り。。。
- ZIPファイル名が日本語の場合、UTF8でURLエンコードする
- CSVファイル名が日本語の場合、環境に合わせる。URLエンコードは不要(例はWindows用としてSJISに変換)
- CSVファイルの中身が日本語の場合、環境に合わせる。(例はWindows用としてSJISに変換)
import csv import urllib import zipfile from django.http.response import HttpResponse def download_csv_zip(request): #### 書き込むzipファイルの準備 memory_file = BytesIO() zip_file = zipfile.ZipFile(memory_file, 'w') #### CSVファイルの書き込み。1ファイル目 csv_file1 = BytesIO() filename1 = (u'CSVファイル1.csv').encode("sjis") writer1 = csv.writer(csv_file1) writer1.writerow(map(lambda n:toSJIS(n), [u'概要', u'詳細'])) writer1.writerow(map(lambda n:toSJIS(n), [u'ああああ', u'いいい'])) ## CSVファイルの内容をzip_fileに書き込む。 zip_file.writestr(filename1, csv_file1.getvalue()) csv_file1.close() #### CSVファイルの書き込み。2ファイル目 csv_file2 = BytesIO() filename2 = (u'CSVファイル2.csv').encode("sjis") writer2 = csv.writer(csv_file2) writer2.writerow(map(lambda n:toSJIS(n), [u'概要', u'詳細'])) writer2.writerow(map(lambda n:toSJIS(n), [u'ああああ', u'いいい'])) ## CSVファイルの内容をzip_fileに書き込む。 zip_file.writestr(filename2, csv_file2.getvalue()) csv_file2.close() #### zipファイルの内容をreponseに設定 zip_file.close() zip_filename = urllib.quote((u'CSVファイル(複数).zip').encode("utf8")) response = HttpResponse(memory_file.getvalue(), content_type='application/zip') response['Content-Disposition'] = 'attachment; filename*=UTF-8\'\'{}'.format(urllib.quote(zip_file_name)) return response def toSJIS(s=""): u'{}'.format(s).encode("sjis")
以上!!
Python、さくっと書くのはいいんだけど、静的型付け言語が好きなので、結構困る。。。
参考になる書籍
- 作者: 関根裕紀,新井正貴
- 出版社/メーカー: シーアンドアール研究所
- 発売日: 2019/07/01
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
- 作者: 掌田津耶乃
- 出版社/メーカー: 秀和システム
- 発売日: 2018/06/09
- メディア: 単行本
- この商品を含むブログを見る
- 作者: 横瀬明仁
- 出版社/メーカー: NextPublishing Authors Press
- 発売日: 2018/08/26
- メディア: オンデマンド (ペーパーバック)
- この商品を含むブログを見る
- 作者: 横瀬明仁
- 発売日: 2018/12/08
- メディア: Kindle版
- この商品を含むブログを見る