Django field 101

错误消息和验证规则

编写验证函数

验证函数只接收一个参数,不需要返回值。验证错误时抛出 forms.ValidationError 异常,该异常的 code 参数用于指定需要显示 error_messages 的键名,没有定义时显示异常的消息

  form django import froms
  import re
  def validate_binary(value):
      if not re.search(r'^[01]+$', value):
        raise forms.ValidationError('default invalid message', code='invalid_number')

使用验证函数和消息

在初始化 Field 类时定义错误消息和验证规则

  binary_string = forms.CharField(error_messages={'invalid_number': 'not binary number'},
                                  validators=[validate_binary])

如果只是简单的正则表达式验证,可以用 RegexField 简写为

  binary_string = forms.CharField(regex=r'^[01]+$', error_message='not binary number')

注意 error_message 没有 s,这个参数是一个字符串代替了 errors_messageinvalid 的值

自定义表单字段

上面提到的方式很适合一些特殊规则。如果经常重复使用一些规则,自定义字段更加方便。如果只是简单的修改验证规则和信息,只需要继承并重写 default_error_messagesdefault_validators 即可

  def validate_username(value):
      if not re.search(r'^[a-z1-9_]+$'):
         raise froms.ValidationError('', code='invalid_charactor')

  class UsernameField(form.Field):
      default_error_messages = {'invalid_charactor': 'invalid_charactor'}
      default_validators = [validate_username]

Django 内建的 Field 并不多,经常无法满足需求。在扩展 Field 前先要了解的 Field 的工作方式

  1. 通过 widget 获取数据,这个动作由 Form 来完成
  2. 调用 to_python 方法转换为 python 对象
  3. 调用 validate 执行验证,需要调用 Field 自身属性的验证规则写在此处
  4. 调用 run_validators 方法执行 default_validators 属性中的验证

例1. 从 request.POST 中获取多条数字记录

  class MultiWidget(forms.Widget):
      def value_from_datadict(self, data, files, name):
          try:
              return data.getlist(name)
          except AttributeError:
              value = data.get(name, [])
              if isinstance(value, (list, tuple)):
                  return list(value)
              return [value]

    class MultiIntegerField(forms.Field):
        widget = MultiWidget

例2. 输入的值和指定的值匹配

  class SelectCharField(forms.CharField):
      def __init__(select, *args, **kwargs):
          self.select = select
          super(SelectCharField, self).__init__(*args, **kwargs)

      def validate(self, value):
          if value not in self.select:
              raise forms.ValidationError('')