https://www.cnblogs.com/pyspark/p/8607801.html
https://www.cnblogs.com/LYliangying/articles/9896548.html
fieids.py mainly defines the sequence of the various fields of the class. Field base class.
class Field
_creation_counter = 0 default_error_messages = { 'required': _('This field is required.'), 'null': _('This field may not be null.') } default_validators = [] #默认验证器初始化为空list default_empty_html = empty initial = None
# In the constructor, the definitions given parameters inherited by subclasses, upon instantiation parameter passing, to control various properties of this field # READ_ONLY, show output for serialization only # WRITE_ONLY, show that only to deserialize input, such as a password # required, that you must enter in the deserialization # default, the default values used when deserializing # Initial # Source, field name # label, when the display API for HTML page displayed # help_text, when the display API for HTML page, field displays help information # style # error_messages, the dictionary contains the error number and the error message # validators, validators of the field used # allow_null, indicate whether the field allows incoming None The default False DEF __init __ (Self, READ_ONLY = False, WRITE_ONLY = False, required = None, default = empty, Initial = empty, Source = None, label = None, help_text = None, style = None, error_messages = None, validators = None, allow_null = False): self._creation_counter = Field._creation_counter Field._creation_counter += 1 # If `required` is unset, then use `True` unless a default is provided. if required is None: required = default is empty and not read_only # Some combinations of keyword arguments do not make sense. # 断言一些没有意义的参数组合 assert not (read_only and write_only), NOT_READ_ONLY_WRITE_ONLY assert not (read_only and required), NOT_READ_ONLY_REQUIRED assert not (required and default is not empty), NOT_REQUIRED_DEFAULT assert not (read_only and self.__class__ == Field), USE_READONLYFIELD # 将传入的参数赋值给实例(属性初始化) self.read_only = read_only self.write_only = write_only self.required = required self.default = default self.source = source self.initial = self.initial if (initial is empty) else initial self.label = label self.help_text = help_text self.style = {} if style is None else style self.allow_null = allow_null if self.default_empty_html is not empty: if default is not empty: self.default_empty_html = default if validators is not None: self.validators = list(validators) # These are set up by `.bind()` when the field is added to a serializer. self.field_name = None self.parent = None # Collect default error message from self and parent classes messages = {} for cls in reversed(self.__class__.__mro__): messages.update(getattr(cls, 'default_error_messages', {})) messages.update(error_messages or {}) self.error_messages = messages
# .validators is a lazily loaded property, that gets its default # value from `get_validators`. # validators属性设置 @property def validators(self): if not hasattr(self, '_validators'): self._validators = self.get_validators() return self._validators @validators.setter def validators(self, validators): self._validators = validators def get_validators(self): return list(self.default_validators)
Subclass
class IntegerField(Field): default_error_messages = { 'invalid': _('A valid integer is required.'), 'max_value': _('Ensure this value is less than or equal to {max_value}.'), 'min_value': _('Ensure this value is greater than or equal to {min_value}.'), 'max_string_length': _('String value too large.') } MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs. re_decimal = re.compile(r'\.0*\s*$') # allow e.g. '1.0' as an int, but not '1.2' def __init__(self, **kwargs): self.min_value = kwargs .pop ( 'min_value', None) the other properties inherited from the parent class # (corresponding parent attribute is common, where the property is unique to the subclass) # Get the variable length parameter passing in max_value, min_value, to give an example, the default None of self.max_value = kwargs .pop ( 'max_value', None) super().__init__(**kwargs) # 如果传参max_value,先拼接error message,然后在validators属性里添加一个验证器元素。 if self.max_value is not None: message = lazy_format(self.error_messages['max_value'], max_value=self.max_value) self.validators.append( MaxValueValidator(self.max_value, message=message)) if self.min_value is not None: message = lazy_format(self.error_messages['min_value'], min_value=self.min_value) self.validators.append( MinValueValidator(self.min_value, message=message)) def to_internal_value(self, data): if isinstance(data, str) and len(data) > self.MAX_STRING_LENGTH: self.fail('max_string_length') try: data = int(self.re_decimal.sub('', str(data))) except (ValueError, TypeError): self.fail('invalid') return data def to_representation(self, value): return int(value)
class CharField(Field): default_error_messages = { 'invalid': _('Not a valid string.'), 'blank': _('This field may not be blank.'), 'max_length': _('Ensure this field has no more than {max_length} characters.'), 'min_length': _('Ensure this field has at least {min_length} characters.'), } initial = '' def __init__(self, **kwargs): self.allow_blank = kwargs.pop('allow_blank', False) self.trim_whitespace = kwargs.pop('trim_whitespace', True) self.max_length = kwargs.pop('max_length', None) self.min_length = kwargs.pop('min_length', None) super().__init__(**kwargs) if self.max_length is not None: message = lazy_format(self.error_messages['max_length'], max_length=self.max_length) self.validators.append( MaxLengthValidator(self.max_length, message=message)) if self.min_length is not None: message = lazy_format(self.error_messages['min_length'], min_length=self.min_length) self.validators.append( MinLengthValidator(self.min_length, message=message)) # ProhibitNullCharactersValidator is None on Django < 2.0 if ProhibitNullCharactersValidator is not None: self.validators.append(ProhibitNullCharactersValidator()) def run_validation(self, data=empty): # Test for the empty string here so that it does not get validated, # and so that subclasses do not need to handle it explicitly # inside the `to_internal_value()` method. if data == '' or (self.trim_whitespace and str(data).strip() == ''): if not self.allow_blank: self.fail('blank') return '' return super().run_validation(data) # 将int,float转为为str def to_internal_value(self, data): # We're lenient with allowing basic numerics to be coerced into strings, # but other types should fail. Eg. unclear if booleans should represent as `true` or `True`, # and composites such as lists are likely user error. if isinstance(data, bool) or not isinstance(data, (str, int, float,)): self.fail('invalid') value = str(data) return value.strip() if self.trim_whitespace else value def to_representation(self, value): return str(value)