例えばタスクというModelを作るとして、
以下のように、タスク名称と、開始日、完了期日、完了日という3つの日付フィールドをつけたとする。
from django.db import models
class Task(models.Model):
def __str__(self):
return self.title
title = models.CharField(max_length=128)
start_at = models.DateField('From')
due_at = models.DateField('Due',blank=True,null=True)
end_at = models.DateField('To',blank=True,null=True)
さて、タスク登録する画面でも作ろうかってなると「開始日と終了日を逆にしたらエラーになるようにしたいな」と思うわけで、Djangoだとどういうやりようがあるのかな、と思ってネットを調べたら
① saveメソッドをオーバーライド
② MetaのConstraintsを使う
③ formのvalidationを使う
くらいの方法が見つかった。
結論は、①が一番よさそうに見えたのでこれで行くことにする。こうしてしまう。
from django.db import models
class Task(models.Model):
def __str__(self):
return self.title
title = models.CharField(max_length=128)
start_at = models.DateField('From')
due_at = models.DateField('Due',blank=True,null=True)
end_at = models.DateField('To',blank=True,null=True)
def save(self, *args, **kwargs):
if ( (self.dueat is not None) and (self.start_at > self.due_at) ):
raise ValidationError("Due date is before Start Date.")
if ( (self.endat is not None) and (self.start_at > self.end_at) ):
raise ValidationError("End date is before Start Date.")
super(Task, self).save(*args, **kwargs)
②は、Django公式のガイドにも何やかや書いてあるんだけど、多分今回やりたいことがそもそもできない。テストもしてないけど、散々頑張ってできなかったっていうオチが何となく予想される。
③はたぶんできるけど、どうもDjangoのFormはあまり信用していなくて細かい使い方がわからないし、先々APIとかバッチ処理とか書いて、直接ModelのSaveとか叩かせたりしたときに効かないだろうから、イヤなのでやめた。ドキュメントもななめ読みしただけでも理解大変そう。
Modelによるデータの保存にsaveメソッド通らないことなんてあるのかな。多分ないからやっぱり①が確実かな、というのがいったん結論。