diff --git a/django/core/validators.py b/django/core/validators.py index 57940a59da..b1c5c053b8 100644 --- a/django/core/validators.py +++ b/django/core/validators.py @@ -65,6 +65,64 @@ class RegexValidator: ) +@deconstructible +class DomainNameValidator(RegexValidator): + message = _("Enter a valid domain name.") + ul = "\u00a1-\uffff" # Unicode letters range (must not be a raw string). + # 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}(? self.max_length: + raise ValidationError(self.message, code=self.code, params={"value": value}) + if not self.accept_idna and not value.isascii(): + raise ValidationError(self.message, code=self.code, params={"value": value}) + super().__call__(value) + + +validate_domain_name = DomainNameValidator() + + @deconstructible class URLValidator(RegexValidator): ul = "\u00a1-\uffff" # Unicode letters range (must not be a raw string). @@ -76,20 +134,10 @@ class URLValidator(RegexValidator): ) 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}(?