I'm trying to add a custom Validator with a regex for username input.
The username should contain only a-z, A-Z, 0-9, and _ and be between 3 and 20 characters.
class Validator(validators.RegexValidator):
regex = r"^[A-Za-z0-9_]{3,20} \Z"
flags = re.ASCII
RegEx works fine when there's no character range i.e. r"^[A-Za-z0-9_] \Z"
And I think {3,20}
is the correct way of specifying the length... so I'm not sure why the regex isn't working.
I get this error re.error: multiple repeat at position 19
regardless of the string that I'm trying to validate.
Full traceback:
backend-web-1 | Traceback (most recent call last):
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/django/core/handlers/exception.py", line 47, in inner
backend-web-1 | response = get_response(request)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/django/core/handlers/base.py", line 181, in _get_response
backend-web-1 | response = wrapped_callback(request, *callback_args, **callback_kwargs)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
backend-web-1 | return view_func(*args, **kwargs)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/django/views/generic/base.py", line 70, in view
backend-web-1 | return self.dispatch(request, *args, **kwargs)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/django/utils/decorators.py", line 43, in _wrapper
backend-web-1 | return bound_method(*args, **kwargs)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/django/views/decorators/debug.py", line 89, in sensitive_post_parameters_wrapper
backend-web-1 | return view(request, *args, **kwargs)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/dj_rest_auth/registration/views.py", line 47, in dispatch
backend-web-1 | return super().dispatch(*args, **kwargs)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/rest_framework/views.py", line 509, in dispatch
backend-web-1 | response = self.handle_exception(exc)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/rest_framework/views.py", line 469, in handle_exception
backend-web-1 | self.raise_uncaught_exception(exc)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/rest_framework/views.py", line 480, in raise_uncaught_exception
backend-web-1 | raise exc
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/rest_framework/views.py", line 506, in dispatch
backend-web-1 | response = handler(request, *args, **kwargs)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/rest_framework/generics.py", line 190, in post
backend-web-1 | return self.create(request, *args, **kwargs)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/dj_rest_auth/registration/views.py", line 66, in create
backend-web-1 | serializer.is_valid(raise_exception=True)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/rest_framework/serializers.py", line 220, in is_valid
backend-web-1 | self._validated_data = self.run_validation(self.initial_data)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/rest_framework/serializers.py", line 419, in run_validation
backend-web-1 | value = self.to_internal_value(data)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/rest_framework/serializers.py", line 478, in to_internal_value
backend-web-1 | validated_value = validate_method(validated_value)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/dj_rest_auth/registration/serializers.py", line 205, in validate_username
backend-web-1 | username = get_adapter().clean_username(username)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/allauth/account/adapter.py", line 255, in clean_username
backend-web-1 | validator(username)
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/django/core/validators.py", line 48, in __call__
backend-web-1 | regex_matches = self.regex.search(str(value))
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/django/utils/functional.py", line 246, in inner
backend-web-1 | self._setup()
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/django/utils/functional.py", line 382, in _setup
backend-web-1 | self._wrapped = self._setupfunc()
backend-web-1 | File "/usr/local/lib/python3.10/site-packages/django/utils/regex_helper.py", line 345, in _compile
backend-web-1 | return re.compile(regex, flags)
backend-web-1 | File "/usr/local/lib/python3.10/re.py", line 251, in compile
backend-web-1 | return _compile(pattern, flags)
backend-web-1 | File "/usr/local/lib/python3.10/re.py", line 303, in _compile
backend-web-1 | p = sre_compile.compile(pattern, flags)
backend-web-1 | File "/usr/local/lib/python3.10/sre_compile.py", line 764, in compile
backend-web-1 | p = sre_parse.parse(p, flags)
backend-web-1 | File "/usr/local/lib/python3.10/sre_parse.py", line 948, in parse
backend-web-1 | p = _parse_sub(source, state, flags & SRE_FLAG_VERBOSE, 0)
backend-web-1 | File "/usr/local/lib/python3.10/sre_parse.py", line 443, in _parse_sub
backend-web-1 | itemsappend(_parse(source, state, verbose, nested 1,
backend-web-1 | File "/usr/local/lib/python3.10/sre_parse.py", line 671, in _parse
backend-web-1 | raise source.error("multiple repeat",
backend-web-1 | re.error: multiple repeat at position 19
CodePudding user response:
This does not really have anything to do with Django. The pattern itself is illegal (at least in Python).
{3,20}
already says "3 to 20 times". Having
(which means "one or more times") immediately after it makes no sense.
The pattern you are looking for is r"^[A-Za-z0-9_]{3,20}\Z"
.
EDIT: Apparently {3,20}
is legal in some regex engines (not Python's), but then
means something else (ie not "one or more times of the last match"). See http://www.rexegg.com/regex-quantifiers.html#possessive (Thanks to @The fourth bird for the link)