【Django】№05：datetimeFieldの日付範囲検索

##経緯
datetimeFieldの日付範囲検索する場合のロジックは№04で解決したが、
dateFieldの場合は、データに時刻が含まれているため、From～Toの同一日付検索ができないという問題が発生。
&emsp;
（以下のロジック補足）
　・date_min･･･検索項目From側
　・date_max･･･検索項目To側
　・datetime･･･データベースdatetimeField


##誤りロジック


```ruby:record_app/views.py

class c_ListView(LoginRequiredMixin,ListView):
    template_name = 'record_app/list.html'
    model = AttendanceModel
    context_object_name = 'object_list'  # デフォルトがobject_listなので名前を変えない場合は本来これは記載しなくてもいい
    def get_queryset(self):

        date_min = self.request.GET.get('date_min')
        date_max = self.request.GET.get('date_max')

        if date_min and date_max:
            object_list = AttendanceModel.objects.filter(datetime__range=[date_min, date_max]).order_by('datetime')
        elif date_min:
            object_list = AttendanceModel.objects.filter(datetime__gte=date_min).order_by('datetime')
        elif date_max:
            object_list = AttendanceModel.objects.filter(datetime__lte=date_max).order_by('datetime')
        else:
            object_list = AttendanceModel.objects.filter(datetime__isnull=True)
        return object_list

i_list = c_ListView.as_view()
```
この場合、データベース側のdatetimeFieldには、時刻が含まれた形でデータが格納されているため、下記のような検索がをすると０件という結果になる。
　例）020/08/05 17:00:03:000138　というデータがあるのに、
　　　2020/08/05~2020/08/05で検索すると、結果は0件となる。


##未解決ロジックＡ
受け取ったdate_min、date_maxに時刻形式を追加して、データベースのdatetimeField形式と同じ形にする。ということをやってみた。

```ruby:record_app/views.py
class c_ListView(LoginRequiredMixin,ListView):
    template_name = 'record_app/list.html'
    model = AttendanceModel
    context_object_name = 'object_list'  # デフォルトがobject_listなので名前を変えない場合は本来これは記載しなくてもいい
    def get_queryset(self):
        date_min = self.request.GET.get('date_min')+ str(' 00:00:00.000000')　#②
        date_max = self.request.GET.get('date_max')+ str(' 23:59:59.999999')　#③

        print ('開始日from' + str(date_min) + '開始日to' + str(date_max))　#①

        if date_min and date_max:
            object_list = AttendanceModel.objects.filter(datetime__range=[date_min, date_max]).order_by('datetime')
        elif date_min:
            object_list = AttendanceModel.objects.filter(datetime__gte=date_min).order_by('datetime')
        elif date_max:
            object_list = AttendanceModel.objects.filter(datetime__lte=date_max).order_by('datetime')
        else:
            object_list = AttendanceModel.objects.filter(datetime__isnull=True)
        return object_list

i_list = c_ListView.as_view()
```
①を記述して検索項目のdate_minとdate_maxに入力した日付をどのような形で受け取っているかを確認したところ、
　「2020-10-01」という日付のみ（時間は無し）の形で受け取っていることが判明。
②よって、②のように、日付の後ろに時間を加えた形に変更するようにした。

→このとき、③は、99:99:99ではエラーとなる。99:99:99.999999でもエラーになる。
　23:59:59.999999だとOK。　本来存在する時間数値でないとエラーになる様子。

→これで、左右同一日付検索は可能になったが、今度は、一方だけの検索でエラーが出るようになってしまった。
&emsp;
&emsp;
###

##未解決ロジックＢ
→　よって、左右両方検索用の検索項目date_min_b、date_max_bを追加した。これで左右両方検索も片方検索も可能になった。

&emsp;
成功したかと思った形）

```ruby:record_app/views.py
class c_ListView(LoginRequiredMixin,ListView):
    template_name = 'record_app/list.html'
    model = AttendanceModel
    context_object_name = 'object_list'  # デフォルトがobject_listなので名前を変えない場合は本来これは記載しなくてもいい
    def get_queryset(self):
        date_min = self.request.GET.get('date_min')
        date_max = self.request.GET.get('date_max')
        date_min_b = self.request.GET.get('date_min')+ str(' 00:00:00.000000')
        date_max_b = self.request.GET.get('date_max')+ str(' 23:59:59.999999')

        #print ('開始日from' + str(date_min) + '開始日to' + str(date_max))

        if date_min and date_max:
            object_list = AttendanceModel.objects.filter(datetime__range=[date_min_b, date_max_b]).order_by('datetime')
        elif date_min:
            object_list = AttendanceModel.objects.filter(datetime__gte=date_min).order_by('datetime')
        elif date_max:
            object_list = AttendanceModel.objects.filter(datetime__lte=date_max).order_by('datetime')
        else:
            object_list = AttendanceModel.objects.filter(datetime__isnull=True)
        return object_list

i_list = c_ListView.as_view()
```
→　しかし、この検索画面を開いている時にロジック変更をした場合は動いたのに、一度ログアウトしてからこの画面を開くとエラーになってしまった。
&emsp;
&emsp;


##解決ロジック♪

時刻形式を追加する”位置”を変更してみたら、うまくいった。
strの付け方が問題ではなかった様子。

　　　　↓この書き方でもOK.
        date_min_b = str(date_min) + str(' 00:00:00.000000')
        date_max_b = str(date_max) + str(' 23:59:59.999999')

　　　　↓この書き方でもOK.
        date_min_b = str(date_min) + ' 00:00:00.000000'
        date_max_b = str(date_max) + ' 23:59:59.999999'

&emsp;
成功最終形）

```ruby:record_app/views.py
class c_ListView(LoginRequiredMixin,ListView):
    template_name = 'record_app/list.html'
    model = AttendanceModel
    context_object_name = 'object_list'  # デフォルトがobject_listなので名前を変えない場合は本来これは記載しなくてもいい
    def get_queryset(self):
        date_min = self.request.GET.get('date_min')
        date_max = self.request.GET.get('date_max')
        date_min_b = str(date_min) + str(' 00:00:00.000000')
        date_max_b = str(date_max) + str(' 23:59:59.999999')

        print ('開始日from' + str(date_min) + '開始日to' + str(date_max))
        print('開始日from' + str(date_min_b) + '開始日to' + str(date_max_b))

        if date_min and date_max:
            object_list = AttendanceModel.objects.filter(datetime__range=[date_min_b, date_max_b]).order_by('datetime')
        elif date_min:
            object_list = AttendanceModel.objects.filter(datetime__gte=date_min_b).order_by('datetime')
        elif date_max:
            object_list = AttendanceModel.objects.filter(datetime__lte=date_max_b).order_by('datetime')
        else:
            object_list = AttendanceModel.objects.filter(datetime__isnull=True)
        return object_list

i_list = c_ListView.as_view()
```