Django 1.7 からマイグレーションシステムが組み込まれました. しかし, このマイグレーションシステムでモデルの DateTimeField にタイムゾーン付きのデフォルト値を設定すると ValueError 例外が送出されます.
問題発生の手順
以下のようなモデルを作成するとします. フィールドのデフォルト値にはそれぞれタイムゾーン付きの現在時刻が設定されています. django.utils.timezone.now は settings.USE_TZ = True の場合にタイムゾーン付きになります.
from datetime import datetime from django.db import models from django.utils.timezone import now, utc class SampleModel(models.Model): added = models.DateTimeField(default=datetime.utcnow().replace(tzinfo=utc)) updated = models.DateTimeField(default=now())
上のモデルについて makemigration を実行すると ValueError が送出されます.
$ python manage.py makemigrations Migrations for 'app': 0001_initial.py: - Create model SampleModel Traceback (most recent call last): File "manage.py", line 10, in <module> execute_from_command_line(sys.argv) 〜〜〜 省略 〜〜〜 File "**********/venv/lib/python3.4/site-packages/django/db/migrations/writer.py", line 271, in serialize raise ValueError("Cannot serialize datetime values with timezones. Either use a callable value for default or remove the timezone.") ValueError: Cannot serialize datetime values with timezones. Either use a callable value for default or remove the timezone.
問題の修正方法
問題の修正方法は ValueError 例外のメッセージに記述されています. (Either use a callable value for default or remove the timezone.) 前者は呼び出し可能オブジェクト (関数など) をデフォルト値に設定する方法で, 後者はタイムゾーン情報のない datetime オブジェクトを設定するというものです. 後者を採用するのはあまり好ましくないケースが多いと思うますが, 修正したモデルは以下のようになります.
from datetime import datetime from django.db import models from django.utils.timezone import now class SampleModel(models.Model): added = models.DateTimeField(default=datetime.utcnow()) updated = models.DateTimeField(default=now)
updated の方は前者の方法を用い, 関数をデフォルト値に設定しています. added の方は datetime.datetime.utcnow が tzinfo = None (タイムゾーン情報のない) の datetime オブジェクトを返すことを用いています.