【Python】Modelクラスでclean_[field_name]メソッドを使う【Django】

2012年1月12日木曜日 18:44 By Unknown , In ,

Djangoのforms.Formクラスにあるアレです。
Modelにも実装してくれればいいのに。。

Modelにもカスタムバリデーション用のcleanメソッドがありますけども、あすこでValidationErrorを投げるとどんな設定してもNON_FIELD_ERRORSのエラーになってしまいます。
こりゃー使いづらいぜーという事なのでFormクラスと似たような事が出来るようにMixinを使って実装をしてみました。
と言ってもDjangoのソースパクって数行追加するだけですけども。

#-*-coding=utf8-*-

from django.core.exceptions import ValidationError

class CleanFieldModelMixin(object):
  """clean_[field_name]メソッドが使えるようになります。"""
  
  def clean_fields(self, exclude=None):
    if exclude is None: exclude = []

    errors = {}
    for f in self._meta.fields:
      if f.name in exclude: continue

      raw_value = getattr(self, f.attname)
      if f.blank and raw_value in validators.EMPTY_VALUES: continue
      
      try:
        setattr(self, f.attname, f.clean(raw_value, self))
        if hasattr(self, 'clean_%s' % f.name):
          value = getattr(self, 'clean_%s' % f.name)()
          setattr(self, f.attname, value)
      except ValidationError, e:
        errors[f.name] = e.messages

    if errors:
      raise ValidationError(errors)

んで、実際の使い方はこんな感じ

#-*-coding=utf8-*-

from django.db import models
from django.core.exceptions import ValidationError
from utils.models import CleanFieldModelMixin # 適当にして下さいな。

# MixinクラスはModelクラスより先に書いてくださいね!
class User(CleanFieldModelMixin, models.Model):
  name = models.CharField('name', max_length=60)
  
  def clean_name(self):
    count = User.objects.filter(name=self.name).count()
    if count > 0:
      raise ValidationError('%s is already exists.' % self.name)

これで動く。
多分動く。。

0 コメント:

コメントを投稿