LoginSignup
8
10

More than 5 years have passed since last update.

【Python3】Djangoで登録されたデータをCSV出力する

Posted at

はじめに

Python(Django)でWebアプリケーション作ってると、「データをCSVで出せるようにしてほしい」という要望はほぼマストなので備忘録的にまとめます。

CSVファイルを生成する

例えば毎月1日に、前月の受注リストなんかを集計してその結果をCSVとして出力する、という動作を考えます。
ファイル名は yymm_billing.csv という命名規則とします。
また、クライアントはWindows端末のExcelでCSVを閲覧することを想定し、文字化けさせないために出力するCSVの文字コードを cp932 とする。
Order テーブルは以下のように定義する。

models.py
class Order(models.Model):
    order_date = models.DateField("受注日", auto_now=False, auto_now_add=False, default=date.today)
    customer = models.CharField("顧客名", max_length=255)
    phone_number = models.CharField("電話番号", max_length=255)
    item = models.CharField("商品名", max_length=255)
    num = models.IntegerField("数量", null=True, blank=True)
    cost = models.IntegerField("原価", null=True, blank=True)
    earnings = models.IntegerField("売上", null=True, blank=True)
    gross_profit = models.IntegerField("粗利", null=True, blank=True)

で、実際のCSV出力の処理ですが、結構長くなってしまった。
日付の計算をするために relativedelta を利用しているので

pip install python-dateutil

でインストールしておきます。

output_csv.py
from datetime import datetime, date, time, timedelta
from dateutil.relativedelta import relativedelta
from myapp.models import Order # モデルは適当です
import csv


"""
例えば2018年10月1日にこのスクリプトを実行すると
/path/to/output_dir に
201810_billing.csv
というファイルが生成されるようにする。
"""
t = date.today()
output_path = '/path/to/output_dir'
output_name = t.strftime('%Y%m') + '_billing.csv'

# 検索対象レコードの抽出
start_date = date.today().replace(day=1) - relativedelta(months=1) # 前月の1日を取得
end_date = date.today().replace(day=1) - timedelta(1) # 前月の最終日を取得

order_list = Order.objects.filter(order_date__gte=start_date)\
                          .filter(order_date__lte=end_date)

# CSV出力処理開始
with open(output_path + output_name, 'w', encoding='cp932', newline='') as csv_file:
    # 1行目にヘッダーを書き込む
    header = ['受注日時', '顧客名', '電話番号', '商品名', '数量', '原価', '売上', '粗利']
    writer = csv.writer(csv_file, quoting=csv.QUOTE_ALL)
    writer.writerow(header)

    for order in order_list:
        order_date = order.order_date
        customer = order.customer
        phone_number = order.phone_number
        item = order.item
        num = order.num
        cost = order.cost
        earnings = order.earnings
        gross_profit = order.gross_profit

        row = []
        row += [order_date, customer, phone_number, item, num, cost, earnings, gross_profit]

        writer.writerow(row)

これで対象のディレクトリに定義した命名規則のCSVが吐き出されるようになります。
あとはダウンロードボタンを作ってあげてファイルをダウンロードできるようにしてあげればOKです。

モデルの定義などはこの記事を書くために適当に用意したものなのであまり参考にしないようお願いします。

8
10
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
10