LoginSignup
7
4

More than 3 years have passed since last update.

DjangoでDateTimeFieldを入力しやすくしたのに、iPhoneで<input type="datetime-local">が上手くいかなかった話

Posted at

こんにちは、現在、大学3年生でエンジニアを目指している「がくじん」といいます。インターンで受け入れてくださるところを募集しておりますので、TwitterのDMお待ちしています。

本記事は、DjangoのDateTimeFieldに<input type="datetime-local>を指定したら、なぜかiPhoneから投稿できなかったので色々試した、という内容です。結果的に<input type="datetime-local>のまま投稿できるようになりました。

DjangoのDateTimeFieldは、標準だとただのテキストボックスで入力するようになっています。しかし、あまりにも入力が面倒で不親切なので、他の入力の方法を探しました。

DateTimeFieldにdatetime-localで入力する

発見したのがHTML5で追加されたという<input type="datetime-local">です。これならカレンダーで日付を入力でき、時間も上下のキーで入力できます。早速、qiitaで見つけた記事を参考に以下のように実装しました。

form.py
from django import forms
from .models import Post
from django.utils import timezone


class CreateForm(forms.Form):
    ...
    start_time = forms.DateTimeField(
        label='開始時刻',
        widget=forms.DateTimeInput(attrs={"type": "datetime-local"}),
        input_formats=['%Y-%m-%dT%H:%M']
    )
    ...

これでDateTimeFieldに入力し、投稿できるようになったと思われたのですが、なぜかiPhoneから入力することができませんでした。Safari for iOSとChrome for iOSどちらともです。PC、Android端末からは投稿できたのにです。

IMG_1061.jpg

レンダリングエンジン、Webkitが原因だった

teratailに質問してみると、iPhoneはレンダリングエンジンとしてWebkitを利用しているのが原因かもしれないと指摘を受けました。Safari for iOSとChrome for iOSは見た目こそ違うものの、レンダリングエンジンはWebkitを利用しているそうです。

また、Mac版SafariもレンダリングエンジンにWebkitを使っていると知り、試してみたところ、やはり投稿ができませんでした。原因はWebkitというレンダリングエンジンだと特定できました。

Webkitの場合、datetime-localに初期値を設定する必要がある

Stack Overflowに同様の質問がされており、初期値を与える必要があると書かれていました。しかし、初期値をハードコードするのは最善策だとは思えず、timezone.datetime.now()を利用して初期値を設定しました。

form.py
from django import forms
from .models import Post
from django.utils import timezone


class CreateForm(forms.Form):
    ...
    start_time = forms.DateTimeField(
        label='開始時刻',
        widget=forms.DateTimeInput(attrs={"type": "datetime-local", "value": timezone.datetime.now()}),
        input_formats=['%Y-%m-%dT%H:%M']
    )
    ...

しかし、このコードでは問題が解決できませんでした。そもそもtimezone.datetime.now()メソッドは非常に細かい時刻まで表示してしまっていました。

結論:strftime()を用いてinput_formatsと形式を合わせる

DjangoはDateTimeFieldを['%Y-%m-%dT%H:%M']の形式で必要とするようです。そのためにinput_formatsで指定していたらしい(コピペなのがバレる)。そこで、初期値もstrftime()を用いて同じ形式に指定してあげる必要がありました。最終的なコードが以下になります。

form.py
from django import forms
from .models import Post
from django.utils import timezone


class CreateForm(forms.Form):
    ...
    start_time = forms.DateTimeField(
        label='開始時刻',
        widget=forms.DateTimeInput(attrs={"type": "datetime-local", "value": timezone.datetime.now().strftime('%Y-%m-%dT%H:%M')}),
        input_formats=['%Y-%m-%dT%H:%M']
    )
    ...
7
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
4