【cygwin/django】DayArchiveViewクラスのオブジェクトに「%Y-%m-%d」形式のパラメータを渡す

# 1. 背景

- チュートリアル、他ではどれも「%Y/%m/%d」形式でパラメータを渡す。
- これを「%Y-%m-%d」形式で渡したかった。
    - 想定していた方法は、DayArchiveViewクラスが対応していなかった。
    - 次善策で対応した。

# 2. 環境

- Windows10/cygwin
- python3.6.10
- Django3.1
- チュートリアルの「mysite」は「config」で作成

# 3. 各ファイルについて

- 動作したファイルそのままではなく、手作業で差し障りのない内容に変更しています。
- ```converters.py``` は未変更。

## 3.1. config/converters.py

```python
from datetime import datetime, date
from config.settings import DEBUG

class YmdConverter:
    regex = '20[0-9]{2}-[01][0-9]-[0123][0-9]'

    def to_python(self, value):
        Ymd = datetime.strptime(value,"%Y-%m-%d")
        if DEBUG: print(Ymd)
        return Ymd
 
    def to_url(self, value):
        Ymd = date.strftime(value,"%Y-%m-%d")
        if DEBUG: print(Ymd)
        return Ymd
```

- ```DEBUG```
    - 設定ファイル中の ```DEBUG``` を利用。
- ```regex```
    - URLパラメータとしての文字列パターンを正規表現で記述。
- ```to_python```
    - 受け取った文字列をview.pyで利用する時のデータ型に変換する。
- ```to_url```
    - python内部で使っていたデータをurlパラーメタ－用に変換する。

## 3.2. myapp/urls.py

該当行のみ引用

```python
from django.urls import register_converter, path
from config import converters
from . import views

register_converter(converters.YmdConverter, 'Ymd')

app_name = "myapp"

urlpatterns = [
    path('<str:shop>/today/'    , views.TodayDiary.as_view() , name='today'),
    path('<str:shop>/<Ymd:day>/', views.DayDiary.as_view(),    name='day'),
]
```

- 型名は、```%Y-%m-%d``` に因んで ```Ymd``` にした。

## 3.3. myapp/view.py

```python
from datetime import date
from django.views import generic

from config.settings import DEBUG
from .models import Diary

class TodayDiary(generic.TodayArchiveView):
    model = Diary
    date_field = "entry_date"
    allow_future = True;

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if DEBUG: print(context)
        return context

class DayDiary(generic.DayArchiveView):
    model = Diary
    allow_future = True
    month_format = "%m"
    date_field = "entry_date"
    context_object_name = "object_list"

    def get_year(self):  return  date.strftime(self.kwargs.get("day",None),"%Y")
    def get_month(self): return  date.strftime(self.kwargs.get("day",None),"%m")
    def get_day(self):   return  date.strftime(self.kwargs.get("day",None),"%d")

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        if DEBUG: print(context)
        return context
```

- ```get_context_data```
    - ここにprint文を仕込んでおくと、どんなデータが使えるのか分かって便利。
- ```get_year```, ```get_month```, ```get_day```
    - year, month, dayをまとめて受け取るメソッドがないっぽい。
    - これで対応するしかなかった。
- ```allow_future```
    - Trueにすると「未来の日付」が有効になる。普通は未設定(```False```)にしておくとお思う。
- ```month_format```
    - デフォルトが ```%b``` なので、変えておかないとエラーになる。
- ```context_object_name```
    - 何も設定しないと、同じ内容で ```object_list```, ```diary_list``` の２つが用意される。
        - ```if DEBUG: print(context)``` が見やすくなるように追加した。

# 4. django/views/generic/dates.py

## 4.1. 現状

```python
521 class BaseDayArchiveView(YearMixin, MonthMixin, DayMixin, BaseDateListView):
522     """List of objects published on a given day."""
523     def get_dated_items(self):
524         """Return (date_list, items, extra_context) for this request."""
525         year = self.get_year()
526         month = self.get_month()
527         day = self.get_day()
528
529         date = _date_from_string(year, self.get_year_format(),
530                                  month, self.get_month_format(),
531                                  day, self.get_day_format())
532
533         return self._get_dated_items(date)
```

- ```year```, ```month```, ```day``` を個別に受け取る事した想定していない。
- 本来というか期待している動作になるには、```def get_date(self}``` が必要。

## 4.2. 希望（未検証）

```python
class BaseDayArchiveView(YearMixin, MonthMixin, DayMixin, BaseDateListView):
    """List of objects published on a given day."""
    def get_date(self):
        """パラメータの状況に合わせてIF文を書く"""
        date = self.date
        if date is None:
            try:
                date = self.kwargs["date"]
            except KeyError:
                try:
                    date = self.request.GET["date"]
                except KeyError:
                    year = self.get_year()
                    month = self.get_month()
                    day = self.get_day()

                    date = _date_from_string(year, self.get_year_format(),
                                             month, self.get_month_format(),
                                             day, self.get_day_format())
        return date
        
    def get_dated_items(self):
        """Return (date_list, items, extra_context) for this request."""
        date = self.get_date()

        return self._get_dated_items(date)
```