今日のできごと2022-11-26

子供(小学生)とお風呂。

私「くらえ、【週末が終わり月曜がやってくる絶望5倍】ビームーー!!」

子「がはっ!!しかしその闇の力、祈祷師の私の力で封じ込める、聖なるお札よその力を封じ込めよ」

私「む、むあああ、キャギギギピシャカーン、しかしお札破壊」

子「なんという闇の力の深さ」

私「この力を抑えることはできない。この攻撃を回避するには、『ポジティブな思考と夢や目標に向かって明るく毎日を進む人格』を手に入れるか『スーパー引きこもりニートとして社会との縁を切る』のいずれかを選ばねばならない」

子「当然、ポジティブ!うおおおおおリア充トランスフォーメーション・・・・!!がはっ(吐血」

私「だいじょうぶか」

とかやってて10分くらいあったまった。

Django Modelのフィールド間でチェック(例えば”開始日”と”終了日”の前後関係)

例えばタスクという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メソッド通らないことなんてあるのかな。多分ないからやっぱり①が確実かな、というのがいったん結論。