LoginSignup
5

More than 3 years have passed since last update.

posted at

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

こんにちは、現在、大学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']
    )
    ...

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
What you can do with signing up
5