DjangoでPandas(DataFrame)を活用する方法

スポンサードリンク



こんにちは。sinyです。

この記事では、DjangoでPandas(DataFrame)を活用する方法についてご紹介します。

django-pandasを利用する。

下記リンクのdjango-pandasを利用すると、Djangoのモデルクラス(テーブルに格納されているデータ)を簡単にDataFrame形式に変換することができます。

 

まずは、基本的な使い方を具体例で説明します。

以下のような家計簿テーブルとカテゴリテーブルを例に説明します。

class Category(models.Model):

    class Meta:
        #カテゴリ
        verbose_name ="カテゴリ"
        verbose_name_plural ="カテゴリ"
      
#カラム名の定義
    category_name = models.CharField(max_length=255,unique=True)

    def __str__(self):
        return self.category_name


class Kakeibo(models.Model):

    class Meta:
      
        verbose_name ="家計簿"
        verbose_name_plural ="家計簿"

    #カラムの定義
    date = models.DateField("日付",default=datetime.now)
    category = models.ForeignKey(Category, on_delete = models.PROTECT, verbose_name="カテゴリ")
    money = models.IntegerField("金額", help_text="単位は日本円")
    quantity = models.IntegerField(verbose_name="数量",default=0)
    memo = models.CharField(verbose_name="メモ", max_length=500)
    regist_date = models.DateTimeField(default=timezone.now)

    def __str__(self):
        return self.memo

 

この家計簿テーブルには以下のようなデータが登録されているとします。

普通に全レコードを取得する場合は以下のコードで取得できます。

from .models import Kakeibo
kakeibo_data = Kakeibo.objects.all()

 

kakeibo_dataはQuerySet形式のデータですが、django-pandasのread_frameを使うことで一発でDataFrame形式に変換することができます。

使い方はめちゃくちゃ簡単で以下の通り。

from django_pandas.io import read_frame
df = read_frame(kakeibo_data, fieldnames=['date', 'category', 'money', 'quantity', 'memo'])

 

read_frameの第1引数にQuerSetデータを指定し、fieldnamesに取得したいテーブルクラスのカラム(属性)をリスト形式で指定するだけです。

dfを表示してみると、以下の通りDataFrame形式に変換されていることが確認できます。

>>> df
          date category  money  quantity       memo
0   2018-12-04       食費   1500         5       ラーメン
1   2018-12-05       食費   1200         2      ファミレス
2   2018-12-06       食費   5000         1         焼肉
3   2018-12-04      交通費    380         3         新宿
4   2018-12-04      交通費    400         2     セミナー参加
5   2018-12-04       雑費   3000         2       書籍購入
6   2018-12-04       雑費   3000         1        飲み会
7   2018-11-19      交通費  14000         2  品川⇔大阪(修正)
8   2018-11-22      交通費   8000         2         出張
9   2018-12-04       雑費   2800         3       書籍購入
10  2018-11-29       雑費   3000         1       書籍購入
11  2019-01-02       食費    480        11         牛丼
12  2019-05-18       食費   3000         1         焼肉
13  2018-10-01       食費    500         5         牛丼
14  2019-05-17       食費   3000         1         焼肉
15  2018-10-31       食費   3000         1         焼肉
16  2018-10-08      交通費    600         2         通勤
17  2018-10-16      交通費    354         3         遊び
18  2018-10-11       雑費  10000         1       パチンコ
19  2018-10-31      電話代   5500         1         携帯
20  2018-11-30      電話代   6500         1         携帯
21  2018-12-31      電話代   7500         1         携帯
22  2019-01-31      電話代   5000         1         携帯
23  2018-12-08       食費   3000         1         食費
24  2018-12-09       食費    390         2         牛肉
25  2019-05-16       食費    500         3         吉牛

 

django-pandasの応用事例

 

データフレームに変換できることはわかったけど、何かうれしい使い方はないかな・・・
ということで、django-pandasの活用方法を考えてみました。

テーブルデータの内容をDataFrame形式に簡単に変換できるなら、to_csvメソッドを組み合わせて「画面のボタンポチ!」でcsv形式のデータを生成→ダウンロード出来たらうれしいかも!
ということで作ってみました。
簡単なデモ動画です。
テーブルに格納されているデータ一覧をcsv形式でダウンロードする機能がほしい!」なんていう要件がある場合は、django-pandasを活用することで上記のような機能を簡単に実装できます。
具体的な実装方法は以下の通りです。

CSV生成用のボタンを定義する。

例えば、一覧表示画面用のテンプレートに以下のようなCSV生成ボタンを定義し、CSVファイル生成ボタンを押すと、URLパターン「kakeibo:export_kakeibo」をCALLするようにしておきます。
<form action='{% url 'kakeibo:export_kakeibo' %}' method='GET' enctype="multipart/form-data">
<div class="btn-group">
 <input type="submit" class="btn btn-primary" value="csvファイル生成" data-toggle="tooltip" data-placement="right"data-html="true">
</div>
</form>

 

urls.pyの設定

CSV生成ボタンが押された際にCALLされるURLパターンを定義します。

例えば、アプリケーション配下のurls.pyのurlpatternsに以下のような定義を追加しておきます。

path('export_kakeibo/', views.export_kakeibo, name='export_kakeibo'),

 

また、プロジェクト直下のurls.pyには以下を追加してCSVが生成されるメディアファイルパスを定義しておきます。

from django.contrib import admin
from django.urls import path
from django.conf.urls import include, url
from django.conf import settings
from django.conf.urls.static import static #add

urlpatterns = [
    path('admin/', admin.site.urls),
    url('kakeibo/', include('kakeibo.urls')),
]

urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)#add

 

ビューの設定

次にviews.pyの設定です。

CSV生成ボタンを押した際にCALLされるexport_kakeibo関数を定義します。

※エラー処理等は一切考慮していない簡単なコード例になってます。

from django.conf import settings

def export_kakeibo(request):
    qs = Kakeibo.objects.all()
    df = read_frame(qs, fieldnames=['date', 'category', 'money', 'quantity', 'memo'])
    exp_path = settings.MEDIA_ROOT + "\\kakeibo_list.csv"
    df.to_csv(exp_path, encoding='utf_8_sig',index=False)
    return render(request, 'kakeibo/kakeibo_export.html')

 

django-pandasのread_frameでDataFrame形式に変換したデータ(qs)を、以下to_csvメソッドを使ってメディアファイルパスにcsv形式で保存しています。

df.to_csv(exp_path, encoding='utf_8_sig',index=False)

 

日本語文字化け対策のために「encoding='utf_8_sig'」、DataFrameのIndexを除外するために「index=False」を指定しています。

これで、メディアファイルパスにcsvファイルが生成されます。

settings.pyには以下のメディアファイルの設定をしておきます。

MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
MEDIA_URL = '/media/'

 

テンプレートの設定

最後に、csvファイル生成ボタンを押した後に表示されるCSVダウンロード画面を定義します。

<div class="alert alert-success alert-dismissible" role="alert">
<a href="http://127.0.0.1:8000/media/kakeibo_list.csv">kakeibo_list.csv</a>
 </div> 

 

非常に簡素に作っていますが、これで以下のような画面が表示されてkakeibo_list.csvをクリックするとメディアディレクトリ上からcsvファイルをダウンロードできるようになります。

一旦メディアディレクトリにcsvを格納しているのが微妙(手間をかけている)な気がしますが、突貫で作ったのでご了承ください。
(ほんとはメモリ内で完結させられれば良いと思いますが・・・)

あと、pandas自体はフィルタリングや集計処理なんかも簡単にできるので、その辺の機能をうまく組み合わせればほしい情報だけを
csvに落とすなんてこともできると思います。

以上、django-pandasの基本操作と活用事例についてでした。

少しでも参考になれば幸いです。

 

おすすめの記事