こんにちは、現在、大学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で見つけた記事を参考に以下のように実装しました。
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端末からは投稿できたのにです。
レンダリングエンジン、Webkitが原因だった
teratailに質問してみると、iPhoneはレンダリングエンジンとしてWebkitを利用しているのが原因かもしれないと指摘を受けました。Safari for iOSとChrome for iOSは見た目こそ違うものの、レンダリングエンジンはWebkitを利用しているそうです。
また、Mac版SafariもレンダリングエンジンにWebkitを使っていると知り、試してみたところ、やはり投稿ができませんでした。原因はWebkitというレンダリングエンジンだと特定できました。
Webkitの場合、datetime-localに初期値を設定する必要がある
Stack Overflowに同様の質問がされており、初期値を与える必要があると書かれていました。しかし、初期値をハードコードするのは最善策だとは思えず、timezone.datetime.now()を利用して初期値を設定しました。
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()を用いて同じ形式に指定してあげる必要がありました。最終的なコードが以下になります。
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']
)
...