pyhaya’s diary

プログラミング、特にPythonについての記事を書きます。Djangoや機械学習などホットな話題をわかりやすく説明していきたいと思います。

Djangoで家計簿のWebアプリケーションを作る 2 月ごとの支出を日付順で表示

前回の記事「Djangoで家計簿のWebアプリケーションを作ってみる」の続きです。今回は、月ごとの支出を表示できるようにコードを書き替えました。

pyhaya.hatenablog.com

その月の支出のみを表示する

前回の段階だと、データベースに登録した支出データをすべて、登録された順に表示していました。今回は、特定の月の支出のみを日付順に表示します。

URLを新しく追加する

money/(年)/(月)というURLでその月の支出を表示できるようにします。

money/urls.py

from django.urls import path
from . import views

app_name = 'money'
urlpatterns = [
        path('', views.index, name='index'),
        # ↓ 追加
        path('<int:year>/<int:month>', views.index, name='index'),
        ]

ビューは新しく作るのが面倒だったのでviews.indexを流用しました。別のものを用意する必要が出てきたら書き換えます。

ビューを書き換える

上の変更で、views.index関数はyearmonthという2つの引数を受け取れるようにしなくてはならなくなりました。ただ、views.indexはmoneyアプリケーションのルートURLを表示する役割もある(引数がないということ)ので、これらの引数にはデフォルト値を入れておきます。

money/view.py

from django.shortcuts import render, redirect
from django.utils import timezone
import pytz
import datetime

from .models import Money
from .forms import SpendingForm
# Create your views here.
TODAY = str(timezone.now()).split('-')    #グローバルで今日の日付を与える

def index(request, year=TODAY[0], month=TODAY[1]):
    money = Money.objects.all()
    for m in money:
        date = str(m.use_date).split(' ')[0]
        m.use_date = '/'.join(date.split('-')[1:3])

    form = SpendingForm()
    context = {'year' : year,
            'month' : month,
            'money' : money,
            'form' : form
            }

    if request.method == 'POST':
        data = request.POST
        use_date = data['use_date']
        cost = data['cost']
        detail = data['detail']

        use_date = timezone.datetime.strptime(use_date, "%Y/%m/%d")
        tokyo_timezone = pytz.timezone('Asia/Tokyo')
        use_date = tokyo_timezone.localize(use_date)
        use_date += datetime.timedelta(hours=9)

        Money.objects.create(
                use_date = use_date,
                detail = detail,
                cost = int(cost),
                )
        return redirect(to='/money/{}/{}'.format(year, month))

    return render(request, 'money/index.html', context)          

特定の月の支出のみを日付順に表示する

特定の月の支出を取り出して、それを日付順に並び替えればよいです。最初のはDjangofilterメソッドが使えます。2番目のものはorder_byメソッドを使えます。

上のコードの12行目を下のように変えれば済みます。

money/views.py

money = Money.objects.filter(use_date__month=month).order_by('use_date')

filterの中身は(フィールド名)__monthでフィールドの月を取得することができます。もちろんフィールドはDataTimeFieldのような、日付系のフィールドでなくてはいけません。filterメソッドのわかりやすい解説を書いている記事としては下のようなものがあります。

codelab.website

フィルターした後は、並び替えです。これはorder_byの引数にMoneyモデルのフィールドであるuse_dateを与えてやれば、使った日順に並び替えがされます。

まとめ

今回は次のことを行いました。

  • index関数に引数を与えて、年と月を指定してその月の支出を表示できるようにした
  • filterメソッドとorder_byメソッドを使ってデータベースから欲しい情報を欲しい形で取り出した