0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

メモ〜cleanメソッドの注意点

Posted at

今回のお題

今回はdjangoのcleanメソッドを使う上での注意点として、自分が引っかかった点を挙げておきます。

一つのフォームにcleanメソッドとclean_xxxメソッドが両方あって、cleanメソッドの方でもxxxフィールドを参照している場合に起こりがちなエラーになります。

エラーが起きた時の状況

モデルとフォームについては以下の通りで、開始日と終了日を選択してキャンペーン情報を登録するという機能を実装していました(関係のない部分については省略しています)。

models.py
from django.db import models

# Create your models here.
class Campaign(models.Model):
  start = models.DateField(
    verbose_name="開始日"
  )
  end = models.DateField(
    verbose_name="終了日"
  )

forms.py
from django.core.exceptions import ValidationError
from .models import Campaign
from django.forms import ModelForm, SelectDateWidget
import datetime
class CampaignForm(ModelForm):
  
  class Meta:
    model = Campaign
    fields = ["menu","campaign_type", "value", "start", "end"]
    widgets = {
      "start": SelectDateWidget,
      "end": SelectDateWidget,
    }

  def clean_start(self):
    start = self.cleaned_data.get("start")
    if start <= datetime.date.today():
      raise ValidationError("開始日は本日以降の日付で入力してください")
    return start

  def clean(self):
    cleaned_data = super().clean()
    start = cleaned_data.get("start")
    end = cleaned_data.get("end")

    if end <= start:
      raise ValidationError("終了日は開始日よりも後の日付で入力してください")
    return cleaned_data

まずclean_startで開始日が今日よりも前になっていないかどうかを確認した後で、cleanメソッドで終了日が開始日以前でないかどうかを確認しています。

発生したエラー

上記のコードを書いた上で、clean_startのテストのために開始日=昨日の日付', 終了日=翌日の日付`と入力したところ以下のエラーが。

TypeError at /campaign/create/
'<=' not supported between instances of 'datetime.date' and 'NoneType'
# 中略
Exception Location:	/Users/hashimotokeishi/cakeshop/cakeshop/campaign/forms.py, line 40, in clean

'<='を用いてdatetimeオブジェクトとNoneTypeを比較することはできないよ。
該当箇所はforms.pyの40行目だよ。

とのこと。

で、該当箇所を見てみると

  def clean(self):
    cleaned_data = super().clean()
    start = cleaned_data.get("start")
    end = cleaned_data.get("end")

    if end <= start: # ここが40行目
      raise ValidationError("終了日は開始日よりも後の日付で入力してください")
    return cleaned_data

の一文がありました。

そもそもcleanメソッドはclean_xxx(今回であればclean_start)の後に呼ばれます。

今回の入力内容であればclean_startでキャンペーン開始日時が弾かれてしまうので、そもそもcleaned_data.get("start")の戻り値はNoneです。

なのでキャンペーン終了日時とNoneを比較することになり、上記のようなエラーが発生してしまったのでした。

解決策

以下のように、startの値が存在しているかどかの確認をしましょう。

if start and start >= end:
0
0
0

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
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?