class JSONField(Field): empty_strings_allowed = False description = _('A JSON object') default_error_messages = { 'invalid': _("Value must be valid JSON."), } def db_type(self, connection): return 'jsonb' def get_transform(self, name): transform = super(JSONField, self).get_transform(name) if transform: return transform return KeyTransformFactory(name) def get_prep_value(self, value): if value is not None: return Json(value) return value def validate(self, value, model_instance): super(JSONField, self).validate(value, model_instance) try: json.dumps(value) except TypeError: raise exceptions.ValidationError( self.error_messages['invalid'], code='invalid', params={'value': value}, ) def value_to_string(self, obj): value = self.value_from_object(obj) return value
def P(self): """ Time, in 12-hour hours, minutes and 'a.m.'/'p.m.', with minutes left off if they're zero and the strings 'midnight' and 'noon' if appropriate. Examples: '1 a.m.', '1:30 p.m.', 'midnight', 'noon', '12:30 p.m.' Proprietary extension. """ if self.data.minute == 0 and self.data.hour == 0: return _('midnight') if self.data.minute == 0 and self.data.hour == 12: return _('noon') return '%s %s' % (self.f(), self.a())
class HStoreField(Field): empty_strings_allowed = False description = _('Map of strings to strings') default_error_messages = { 'not_a_string': _('The value of "%(key)s" is not a string.'), } def db_type(self, connection): return 'hstore' def get_transform(self, name): transform = super(HStoreField, self).get_transform(name) if transform: return transform return KeyTransformFactory(name) def validate(self, value, model_instance): super(HStoreField, self).validate(value, model_instance) for key, val in value.items(): if not isinstance(val, six.string_types): raise exceptions.ValidationError( self.error_messages['not_a_string'], code='not_a_string', params={'key': key}, ) def to_python(self, value): if isinstance(value, six.string_types): value = json.loads(value) return value def value_to_string(self, obj): return json.dumps(self.value_from_object(obj)) def get_prep_value(self, value): value = super(HStoreField, self).get_prep_value(value) if isinstance(value, dict): prep_value = {} for key, val in value.items(): key = force_text(key) if val is not None: val = force_text(val) prep_value[key] = val value = prep_value if isinstance(value, list): value = [force_text(item) for item in value] return value
class RangeMaxValueValidator(MaxValueValidator): def compare(self, a, b): return a.upper > b message = _( 'Ensure that this range is completely less than or equal to %(limit_value)s.' )
class MinValueValidator(BaseValidator): message = _( 'Ensure this value is greater than or equal to %(limit_value)s.') code = 'min_value' def compare(self, a, b): return a < b
class RangeMinValueValidator(MinValueValidator): def compare(self, a, b): return a.lower < b message = _( 'Ensure that this range is completely greater than or equal to %(limit_value)s.' )
class BaseValidator(object): message = _('Ensure this value is %(limit_value)s (it is %(show_value)s).') code = 'limit_value' def __init__(self, limit_value, message=None): self.limit_value = limit_value if message: self.message = message def __call__(self, value): cleaned = self.clean(value) params = { 'limit_value': self.limit_value, 'show_value': cleaned, 'value': value } if self.compare(cleaned, self.limit_value): raise ValidationError(self.message, code=self.code, params=params) def __eq__(self, other): return (isinstance(other, self.__class__) and self.limit_value == other.limit_value and self.message == other.message and self.code == other.code) def compare(self, a, b): return a is not b def clean(self, x): return x
def validate_ipv46_address(value): try: validate_ipv4_address(value) except ValidationError: try: validate_ipv6_address(value) except ValidationError: raise ValidationError(_('Enter a valid IPv4 or IPv6 address.'), code='invalid')
class KeysValidator(object): """A validator designed for HStore to require/restrict keys.""" messages = { 'missing_keys': _('Some keys were missing: %(keys)s'), 'extra_keys': _('Some unknown keys were provided: %(keys)s'), } strict = False def __init__(self, keys, strict=False, messages=None): self.keys = set(keys) self.strict = strict if messages is not None: self.messages = copy.copy(self.messages) self.messages.update(messages) def __call__(self, value): keys = set(value.keys()) missing_keys = self.keys - keys if missing_keys: raise ValidationError( self.messages['missing_keys'], code='missing_keys', params={'keys': ', '.join(missing_keys)}, ) if self.strict: extra_keys = keys - self.keys if extra_keys: raise ValidationError( self.messages['extra_keys'], code='extra_keys', params={'keys': ', '.join(extra_keys)}, ) def __eq__(self, other): return (isinstance(other, self.__class__) and self.keys == other.keys and self.messages == other.messages and self.strict == other.strict) def __ne__(self, other): return not (self == other)
class PostgresConfig(AppConfig): name = 'arouse._dj.contrib.postgres' verbose_name = _('PostgreSQL extensions') def ready(self): connection_created.connect(register_hstore_handler) CharField.register_lookup(Unaccent) TextField.register_lookup(Unaccent) CharField.register_lookup(SearchLookup) TextField.register_lookup(SearchLookup) CharField.register_lookup(TrigramSimilar) TextField.register_lookup(TrigramSimilar)
class RegexValidator(object): regex = '' message = _('Enter a valid value.') code = 'invalid' inverse_match = False flags = 0 def __init__(self, regex=None, message=None, code=None, inverse_match=None, flags=None): if regex is not None: self.regex = regex if message is not None: self.message = message if code is not None: self.code = code if inverse_match is not None: self.inverse_match = inverse_match if flags is not None: self.flags = flags if self.flags and not isinstance(self.regex, six.string_types): raise TypeError( "If the flags are set, regex must be a regular expression string." ) self.regex = _lazy_re_compile(self.regex, self.flags) def __call__(self, value): """ Validates that the input matches the regular expression if inverse_match is False, otherwise raises ValidationError. """ if not (self.inverse_match is not bool( self.regex.search(force_text(value)))): raise ValidationError(self.message, code=self.code) def __eq__(self, other): return (isinstance(other, RegexValidator) and self.regex.pattern == other.regex.pattern and self.regex.flags == other.regex.flags and (self.message == other.message) and (self.code == other.code) and (self.inverse_match == other.inverse_match)) def __ne__(self, other): return not (self == other)
def get_text_list(list_, last_word=ugettext_lazy('or')): """ >>> get_text_list(['a', 'b', 'c', 'd']) 'a, b, c or d' >>> get_text_list(['a', 'b', 'c'], 'and') 'a, b and c' >>> get_text_list(['a', 'b'], 'and') 'a and b' >>> get_text_list(['a']) 'a' >>> get_text_list([]) '' """ if len(list_) == 0: return '' if len(list_) == 1: return force_text(list_[0]) return '%s %s %s' % ( # Translators: This string is used as a separator between list elements _(', ').join(force_text(i) for i in list_[:-1]), force_text(last_word), force_text(list_[-1]))
def validate_ipv6_address(value): if not is_valid_ipv6_address(value): raise ValidationError(_('Enter a valid IPv6 address.'), code='invalid')
class FileField(Field): # The class to wrap instance attributes in. Accessing the file object off # the instance will always return an instance of attr_class. attr_class = FieldFile # The descriptor to use for accessing the attribute off of the class. descriptor_class = FileDescriptor description = _("File") def __init__(self, verbose_name=None, name=None, upload_to='', storage=None, **kwargs): self._primary_key_set_explicitly = 'primary_key' in kwargs self._unique_set_explicitly = 'unique' in kwargs self.storage = storage or default_storage self.upload_to = upload_to kwargs['max_length'] = kwargs.get('max_length', 100) super(FileField, self).__init__(verbose_name, name, **kwargs) def check(self, **kwargs): errors = super(FileField, self).check(**kwargs) errors.extend(self._check_unique()) errors.extend(self._check_primary_key()) return errors def _check_unique(self): if self._unique_set_explicitly: return [ checks.Error( "'unique' is not a valid argument for a %s." % self.__class__.__name__, obj=self, id='fields.E200', ) ] else: return [] def _check_primary_key(self): if self._primary_key_set_explicitly: return [ checks.Error( "'primary_key' is not a valid argument for a %s." % self.__class__.__name__, obj=self, id='fields.E201', ) ] else: return [] def deconstruct(self): name, path, args, kwargs = super(FileField, self).deconstruct() if kwargs.get("max_length") == 100: del kwargs["max_length"] kwargs['upload_to'] = self.upload_to if self.storage is not default_storage: kwargs['storage'] = self.storage return name, path, args, kwargs def get_internal_type(self): return "FileField" def get_prep_value(self, value): "Returns field's value prepared for saving into a database." value = super(FileField, self).get_prep_value(value) # Need to convert File objects provided via a form to unicode for database insertion if value is None: return None return six.text_type(value) def pre_save(self, model_instance, add): "Returns field's value just before saving." file = super(FileField, self).pre_save(model_instance, add) if file and not file._committed: # Commit the file to storage prior to saving the model file.save(file.name, file, save=False) return file def contribute_to_class(self, cls, name, **kwargs): super(FileField, self).contribute_to_class(cls, name, **kwargs) setattr(cls, self.name, self.descriptor_class(self)) def get_directory_name(self): warnings.warn( 'FileField now delegates file name and folder processing to the ' 'storage. get_directory_name() will be removed in Django 2.0.', RemovedInDjango20Warning, stacklevel=2) return os.path.normpath( force_text(datetime.datetime.now().strftime( force_str(self.upload_to)))) def get_filename(self, filename): warnings.warn( 'FileField now delegates file name and folder processing to the ' 'storage. get_filename() will be removed in Django 2.0.', RemovedInDjango20Warning, stacklevel=2) return os.path.normpath( self.storage.get_valid_name(os.path.basename(filename))) def generate_filename(self, instance, filename): """ Apply (if callable) or prepend (if a string) upload_to to the filename, then delegate further processing of the name to the storage backend. Until the storage layer, all file paths are expected to be Unix style (with forward slashes). """ if callable(self.upload_to): filename = self.upload_to(instance, filename) else: dirname = force_text(datetime.datetime.now().strftime( force_str(self.upload_to))) filename = posixpath.join(dirname, filename) return self.storage.generate_filename(filename) def save_form_data(self, instance, data): # Important: None means "no change", other false value means "clear" # This subtle distinction (rather than a more explicit marker) is # needed because we need to consume values that are also sane for a # regular (non Model-) Form to find in its cleaned_data dictionary. if data is not None: # This value will be converted to unicode and stored in the # database, so leaving False as-is is not acceptable. if not data: data = '' setattr(instance, self.name, data)
class URLValidator(RegexValidator): ul = '\u00a1-\uffff' # unicode letters range (must be a unicode string, not a raw string) # IP patterns ipv4_re = r'(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)(?:\.(?:25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}' ipv6_re = r'\[[0-9a-f:\.]+\]' # (simple regex, validated later) # Host patterns hostname_re = r'[a-z' + ul + r'0-9](?:[a-z' + ul + r'0-9-]{0,61}[a-z' + ul + r'0-9])?' # Max length for domain name labels is 63 characters per RFC 1034 sec. 3.1 domain_re = r'(?:\.(?!-)[a-z' + ul + r'0-9-]{1,63}(?<!-))*' tld_re = ( '\.' # dot '(?!-)' # can't start with a dash '(?:[a-z' + ul + '-]{2,63}' # domain label '|xn--[a-z0-9]{1,59})' # or punycode label '(?<!-)' # can't end with a dash '\.?' # may have a trailing dot ) host_re = '(' + hostname_re + domain_re + tld_re + '|localhost)' regex = _lazy_re_compile( r'^(?:[a-z0-9\.\-\+]*)://' # scheme is validated separately r'(?:\S+(?::\S*)?@)?' # user:pass authentication r'(?:' + ipv4_re + '|' + ipv6_re + '|' + host_re + ')' r'(?::\d{2,5})?' # port r'(?:[/?#][^\s]*)?' # resource path r'\Z', re.IGNORECASE) message = _('Enter a valid URL.') schemes = ['http', 'https', 'ftp', 'ftps'] def __init__(self, schemes=None, **kwargs): super(URLValidator, self).__init__(**kwargs) if schemes is not None: self.schemes = schemes def __call__(self, value): value = force_text(value) # Check first if the scheme is valid scheme = value.split('://')[0].lower() if scheme not in self.schemes: raise ValidationError(self.message, code=self.code) # Then check full URL try: super(URLValidator, self).__call__(value) except ValidationError as e: # Trivial case failed. Try for possible IDN domain if value: try: scheme, netloc, path, query, fragment = urlsplit(value) except ValueError: # for example, "Invalid IPv6 URL" raise ValidationError(self.message, code=self.code) try: netloc = netloc.encode('idna').decode( 'ascii') # IDN -> ACE except UnicodeError: # invalid domain part raise e url = urlunsplit((scheme, netloc, path, query, fragment)) super(URLValidator, self).__call__(url) else: raise else: # Now verify IPv6 in the netloc part host_match = re.search(r'^\[(.+)\](?::\d{2,5})?$', urlsplit(value).netloc) if host_match: potential_ip = host_match.groups()[0] try: validate_ipv6_address(potential_ip) except ValidationError: raise ValidationError(self.message, code=self.code) url = value # The maximum length of a full host name is 253 characters per RFC 1034 # section 3.1. It's defined to be 255 bytes or less, but this includes # one byte for the length of the name and one byte for the trailing dot # that's used to indicate absolute names in DNS. if len(urlsplit(value).netloc) > 253: raise ValidationError(self.message, code=self.code)
class MaxValueValidator(BaseValidator): message = _('Ensure this value is less than or equal to %(limit_value)s.') code = 'max_value' def compare(self, a, b): return a > b
class ImageField(FileField): attr_class = ImageFieldFile descriptor_class = ImageFileDescriptor description = _("Image") def __init__(self, verbose_name=None, name=None, width_field=None, height_field=None, **kwargs): self.width_field, self.height_field = width_field, height_field super(ImageField, self).__init__(verbose_name, name, **kwargs) def check(self, **kwargs): errors = super(ImageField, self).check(**kwargs) errors.extend(self._check_image_library_installed()) return errors def _check_image_library_installed(self): try: from PIL import Image # NOQA except ImportError: return [ checks.Error( 'Cannot use ImageField because Pillow is not installed.', hint=('Get Pillow at https://pypi.python.org/pypi/Pillow ' 'or run command "pip install Pillow".'), obj=self, id='fields.E210', ) ] else: return [] def deconstruct(self): name, path, args, kwargs = super(ImageField, self).deconstruct() if self.width_field: kwargs['width_field'] = self.width_field if self.height_field: kwargs['height_field'] = self.height_field return name, path, args, kwargs def contribute_to_class(self, cls, name, **kwargs): super(ImageField, self).contribute_to_class(cls, name, **kwargs) # Attach update_dimension_fields so that dimension fields declared # after their corresponding image field don't stay cleared by # Model.__init__, see bug #11196. # Only run post-initialization dimension update on non-abstract models if not cls._meta.abstract: signals.post_init.connect(self.update_dimension_fields, sender=cls) def update_dimension_fields(self, instance, force=False, *args, **kwargs): """ Updates field's width and height fields, if defined. This method is hooked up to model's post_init signal to update dimensions after instantiating a model instance. However, dimensions won't be updated if the dimensions fields are already populated. This avoids unnecessary recalculation when loading an object from the database. Dimensions can be forced to update with force=True, which is how ImageFileDescriptor.__set__ calls this method. """ # Nothing to update if the field doesn't have dimension fields or if # the field is deferred. has_dimension_fields = self.width_field or self.height_field if not has_dimension_fields or self.attname not in instance.__dict__: return # getattr will call the ImageFileDescriptor's __get__ method, which # coerces the assigned value into an instance of self.attr_class # (ImageFieldFile in this case). file = getattr(instance, self.attname) # Nothing to update if we have no file and not being forced to update. if not file and not force: return dimension_fields_filled = not ( (self.width_field and not getattr(instance, self.width_field)) or (self.height_field and not getattr(instance, self.height_field))) # When both dimension fields have values, we are most likely loading # data from the database or updating an image field that already had # an image stored. In the first case, we don't want to update the # dimension fields because we are already getting their values from the # database. In the second case, we do want to update the dimensions # fields and will skip this return because force will be True since we # were called from ImageFileDescriptor.__set__. if dimension_fields_filled and not force: return # file should be an instance of ImageFieldFile or should be None. if file: width = file.width height = file.height else: # No file, so clear dimensions fields. width = None height = None # Update the width and height fields. if self.width_field: setattr(instance, self.width_field, width) if self.height_field: setattr(instance, self.height_field, height)
class ArrayField(Field): empty_strings_allowed = False default_error_messages = { 'item_invalid': _('Item %(nth)s in the array did not validate: '), 'nested_array_mismatch': _('Nested arrays must have the same length.'), } def __init__(self, base_field, size=None, **kwargs): self.base_field = base_field self.size = size if self.size: self.default_validators = self.default_validators[:] self.default_validators.append(ArrayMaxLengthValidator(self.size)) # For performance, only add a from_db_value() method if the base field # implements it. if hasattr(self.base_field, 'from_db_value'): self.from_db_value = self._from_db_value super(ArrayField, self).__init__(**kwargs) @property def model(self): try: return self.__dict__['model'] except KeyError: raise AttributeError("'%s' object has no attribute 'model'" % self.__class__.__name__) @model.setter def model(self, model): self.__dict__['model'] = model self.base_field.model = model def check(self, **kwargs): errors = super(ArrayField, self).check(**kwargs) if self.base_field.remote_field: errors.append( checks.Error('Base field for array cannot be a related field.', obj=self, id='postgres.E002')) else: # Remove the field name checks as they are not needed here. base_errors = self.base_field.check() if base_errors: messages = '\n '.join('%s (%s)' % (error.msg, error.id) for error in base_errors) errors.append( checks.Error('Base field for array has errors:\n %s' % messages, obj=self, id='postgres.E001')) return errors def set_attributes_from_name(self, name): super(ArrayField, self).set_attributes_from_name(name) self.base_field.set_attributes_from_name(name) @property def description(self): return 'Array of %s' % self.base_field.description def db_type(self, connection): size = self.size or '' return '%s[%s]' % (self.base_field.db_type(connection), size) def get_db_prep_value(self, value, connection, prepared=False): if isinstance(value, list) or isinstance(value, tuple): return [ self.base_field.get_db_prep_value(i, connection, prepared=False) for i in value ] return value def deconstruct(self): name, path, args, kwargs = super(ArrayField, self).deconstruct() if path == 'arouse._dj.contrib.postgres.fields.array.ArrayField': path = 'arouse._dj.contrib.postgres.fields.ArrayField' kwargs.update({ 'base_field': self.base_field, 'size': self.size, }) return name, path, args, kwargs def to_python(self, value): if isinstance(value, six.string_types): # Assume we're deserializing vals = json.loads(value) value = [self.base_field.to_python(val) for val in vals] return value def _from_db_value(self, value, expression, connection, context): if value is None: return value return [ self.base_field.from_db_value(item, expression, connection, context) for item in value ] def value_to_string(self, obj): values = [] vals = self.value_from_object(obj) base_field = self.base_field for val in vals: if val is None: values.append(None) else: obj = AttributeSetter(base_field.attname, val) values.append(base_field.value_to_string(obj)) return json.dumps(values) def get_transform(self, name): transform = super(ArrayField, self).get_transform(name) if transform: return transform try: index = int(name) except ValueError: pass else: index += 1 # postgres uses 1-indexing return IndexTransformFactory(index, self.base_field) try: start, end = name.split('_') start = int(start) + 1 end = int( end) # don't add one here because postgres slices are weird except ValueError: pass else: return SliceTransformFactory(start, end) def validate(self, value, model_instance): super(ArrayField, self).validate(value, model_instance) for index, part in enumerate(value): try: self.base_field.validate(part, model_instance) except exceptions.ValidationError as error: raise prefix_validation_error( error, prefix=self.error_messages['item_invalid'], code='item_invalid', params={'nth': index}, ) if isinstance(self.base_field, ArrayField): if len({len(i) for i in value}) > 1: raise exceptions.ValidationError( self.error_messages['nested_array_mismatch'], code='nested_array_mismatch', ) def run_validators(self, value): super(ArrayField, self).run_validators(value) for index, part in enumerate(value): try: self.base_field.run_validators(part) except exceptions.ValidationError as error: raise prefix_validation_error( error, prefix=self.error_messages['item_invalid'], code='item_invalid', params={'nth': index}, )
def clean_ipv6_address(ip_str, unpack_ipv4=False, error_message=_("This is not a valid IPv6 address.")): """ Cleans an IPv6 address string. Validity is checked by calling is_valid_ipv6_address() - if an invalid address is passed, ValidationError is raised. Replaces the longest continuous zero-sequence with "::" and removes leading zeroes and makes sure all hextets are lowercase. Args: ip_str: A valid IPv6 address. unpack_ipv4: if an IPv4-mapped address is found, return the plain IPv4 address (default=False). error_message: An error message used in the ValidationError. Returns: A compressed IPv6 address, or the same value """ best_doublecolon_start = -1 best_doublecolon_len = 0 doublecolon_start = -1 doublecolon_len = 0 if not is_valid_ipv6_address(ip_str): raise ValidationError(error_message, code='invalid') # This algorithm can only handle fully exploded # IP strings ip_str = _explode_shorthand_ip_string(ip_str) ip_str = _sanitize_ipv4_mapping(ip_str) # If needed, unpack the IPv4 and return straight away # - no need in running the rest of the algorithm if unpack_ipv4: ipv4_unpacked = _unpack_ipv4(ip_str) if ipv4_unpacked: return ipv4_unpacked hextets = ip_str.split(":") for index in range(len(hextets)): # Remove leading zeroes if '.' not in hextets[index]: hextets[index] = hextets[index].lstrip('0') if not hextets[index]: hextets[index] = '0' # Determine best hextet to compress if hextets[index] == '0': doublecolon_len += 1 if doublecolon_start == -1: # Start of a sequence of zeros. doublecolon_start = index if doublecolon_len > best_doublecolon_len: # This is the longest sequence of zeros so far. best_doublecolon_len = doublecolon_len best_doublecolon_start = doublecolon_start else: doublecolon_len = 0 doublecolon_start = -1 # Compress the most suitable hextet if best_doublecolon_len > 1: best_doublecolon_end = (best_doublecolon_start + best_doublecolon_len) # For zeros at the end of the address. if best_doublecolon_end == len(hextets): hextets += [''] hextets[best_doublecolon_start:best_doublecolon_end] = [''] # For zeros at the beginning of the address. if best_doublecolon_start == 0: hextets = [''] + hextets result = ":".join(hextets) return result.lower()
def A(self): "'AM' or 'PM'" if self.data.hour > 11: return _('PM') return _('AM')
class EmailValidator(object): message = _('Enter a valid email address.') code = 'invalid' user_regex = _lazy_re_compile( r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*\Z" # dot-atom r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"\Z)', # quoted-string re.IGNORECASE) domain_regex = _lazy_re_compile( # max length for domain name labels is 63 characters per RFC 1034 r'((?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+)(?:[A-Z0-9-]{2,63}(?<!-))\Z', re.IGNORECASE) literal_regex = _lazy_re_compile( # literal form, ipv4 or ipv6 address (SMTP 4.1.3) r'\[([A-f0-9:\.]+)\]\Z', re.IGNORECASE) domain_whitelist = ['localhost'] def __init__(self, message=None, code=None, whitelist=None): if message is not None: self.message = message if code is not None: self.code = code if whitelist is not None: self.domain_whitelist = whitelist def __call__(self, value): value = force_text(value) if not value or '@' not in value: raise ValidationError(self.message, code=self.code) user_part, domain_part = value.rsplit('@', 1) if not self.user_regex.match(user_part): raise ValidationError(self.message, code=self.code) if (domain_part not in self.domain_whitelist and not self.validate_domain_part(domain_part)): # Try for possible IDN domain-part try: domain_part = domain_part.encode('idna').decode('ascii') if self.validate_domain_part(domain_part): return except UnicodeError: pass raise ValidationError(self.message, code=self.code) def validate_domain_part(self, domain_part): if self.domain_regex.match(domain_part): return True literal_match = self.literal_regex.match(domain_part) if literal_match: ip_address = literal_match.group(1) try: validate_ipv46_address(ip_address) return True except ValidationError: pass return False def __eq__(self, other): return (isinstance(other, EmailValidator) and (self.domain_whitelist == other.domain_whitelist) and (self.message == other.message) and (self.code == other.code))
def a(self): "'a.m.' or 'p.m.'" if self.data.hour > 11: return _('p.m.') return _('a.m.')
validate_ipv6_address(potential_ip) except ValidationError: raise ValidationError(self.message, code=self.code) url = value # The maximum length of a full host name is 253 characters per RFC 1034 # section 3.1. It's defined to be 255 bytes or less, but this includes # one byte for the length of the name and one byte for the trailing dot # that's used to indicate absolute names in DNS. if len(urlsplit(value).netloc) > 253: raise ValidationError(self.message, code=self.code) integer_validator = RegexValidator( _lazy_re_compile('^-?\d+\Z'), message=_('Enter a valid integer.'), code='invalid', ) def validate_integer(value): return integer_validator(value) @deconstructible class EmailValidator(object): message = _('Enter a valid email address.') code = 'invalid' user_regex = _lazy_re_compile( r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*\Z" # dot-atom r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-\011\013\014\016-\177])*"\Z)', # quoted-string