Help us understand the problem. What is going on with this article?

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

More than 1 year has passed since last update.

はじめに

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です。

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

otera05
Python / AWS / GCP / 最近は Golang
so-tech
SO Technologiesは、日本全国の中小企業向けに最適な、テクノロジーを駆使したサービスを提供します。店舗集客、人材育成、Web広告の統合管理や運用代行の支援など。
https://www.so-tech.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away