db.models.Model
をサブクラス化する際に、チェック/制約を追加することが不可欠な場合があります。
例えば。 start_date
とend_date
のEvent
モデルがあります。
end_date > start_date
になるように、フィールドまたはモデルに検証を追加したいと思います。
これを行うための可能な方法はいくつありますか?
少なくとも、これはModelForm
検証内のmodels.Model
外で実行できることを私は知っています。
しかし、フィールドとmodels.Model
にアタッチする方法は?
このような制約をsaveメソッドに入れません。手遅れです。そこで例外を発生させても、データを間違った方法で入力したユーザーの助けにはなりません。データが500になり、エラーなどのフォームが返されなくなるためです。
Forms/ModelFormsのcleanメソッドでこれを実際にチェックし、ValidationErrorを発生させる必要があるため、form.is_valid()
はfalseを返し、フォーム内のエラーをユーザーに返送して修正することができます。
また、バージョン1.2以降、Djangoには モデル検証 があります。
次のようになります。
class Foo(models.Model):
# ... model stuff...
def clean(self):
if self.start_date > self.end_date:
raise ValidationError('Start date is after end date')
モデルのsaveメソッド内で実行します。
def save(self, *args, **kwargs):
if(self.end_date > self.start_date):
super(Foo, self).save(*args, **kwargs)
else:
raise Exception, "end_date should be greater than start_date"
@stefanwが言うように、フォームのクリーンなメソッドをチェックインする方がユーザーエクスペリエンスが向上します。
値を変更する別の方法がない、または今後もそうなることがないと確信している場合は、これで十分です。ただし、それを確信できることはめったにないため、データベースの整合性が重要な場合は、フォームに加えて、次のいずれかのチェックを追加できます。
データベースの整合性を「完全に」確認するために、データベースレベルの制約を追加できます。例えば。 RunSQL とSQLを使用して、(テストされていない)次のような移行を作成できます。
migrations.RunSQL('ALTER TABLE app_event ADD CONSTRAINT chronology CHECK (start_date > end_date);')
(未検証)。これはデータベースに依存する可能性がありますが、これはもちろん欠点です。
あなたの例では、おそらくそれは価値がなく(間違った開始/終了時間は少し奇妙に見えますが、1つの一貫性のないイベントにのみ影響します)、手動でスキーマを変更する必要はありません。ただし、一貫性が重要な場合に役立ちます。
[〜#〜] edit [〜#〜]:開始時間と終了時間の代わりに、開始時間と期間を保存することもできます。
今日の時点で、 postgres 9.4 と MS SQL Server> = 2008 の両方がSQLのチェック制約をサポートしています。これに加えて、 Django issue 11964 があり、昨日からレビューの準備ができているようです。これがDjango 2。プロジェクトに統合されることを願っています。 rapilabs/Django-db-constraints これも実装しているようです。