Django 1.7 で DateTimeField にタイムゾーン付きのデフォルト値を設定して makemigration できない

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 オブジェクトを返すことを用いています.

参考

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です