[Django] #35578: Customizing `username_validator` in custom User model extending `django.contrib.auth.models.AbstractUser` doesn't work

0 views
Skip to first unread message

Django

unread,
11:20 AM (7 hours ago) 11:20 AM
to django-...@googlegroups.com
#35578: Customizing `username_validator` in custom User model extending
`django.contrib.auth.models.AbstractUser` doesn't work
------------------------------+-----------------------------------------
Reporter: Oscar Rovira | Type: Uncategorized
Status: new | Component: contrib.auth
Version: 5.0 | Severity: Normal
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
------------------------------+-----------------------------------------
Hi there!
I'm sorry if that is the expected behaviour of what I'm going to report,
but looking at the implementation, it should work as I expected.
I have my own authentication `User` model, extending from `AbstracUser`.
Looking at the code of `AbstractUser`, one may think that defining the
class prop `username_validator`, the validation of the username at all the
levels (createsuperuser command, Admin create user form,
User.objects.create_user, ...) should use the new validator provided in
the customized class. It is not working like that. In order to make it
work, one has to re-define also the `username` field in the customized
model.

So, I have the following:
{{{
@deconstructible
class CustomUnicodeUsernameValidator(validators.RegexValidator):
"""Overrides the default username validator from Django Abstract
User to avoid usernames with characters '@', '+' or '.'
"""
regex = r"^[\w-]+\Z"
message = _(
"Enter a valid username. This value may contain only letters, "
"numbers, and -/_ characters."
)
flags = 0

...
class User(AbstractUser):
"""Main app user, extending default Django users."""

# overriding the one defined in AbstractUser
username_validator = CustomUnicodeUsernameValidator() # type: ignore

# Other custom fields
...
}}}

and it does not work, the custom username_validator is not being used.

However, if I redefine the `username` field, including the
`validators=[username_validator]` attribute, it works as expected.
As I said, maybe it is the expected behaviour, and it's just a lack of
documentation.

Thanks!
--
Ticket URL: <https://code.djangoproject.com/ticket/35578>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
2:31 PM (4 hours ago) 2:31 PM
to django-...@googlegroups.com
#35578: Customizing `username_validator` in custom User model extending
`django.contrib.auth.models.AbstractUser` doesn't work
-------------------------------+--------------------------------------
Reporter: Oscar Rovira | Owner: (none)
Type: Uncategorized | Status: closed
Component: contrib.auth | Version: 5.0
Severity: Normal | Resolution: invalid
Keywords: | Triage Stage: Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------+--------------------------------------
Changes (by Natalia Bidart):

* resolution: => invalid
* status: new => closed

Comment:

Hello Oscar, thank you for your report. What you are describing is
explained by how Python class definition works, this is not about Django.
See this simpler example:
{{{#!python
In [1]: class Abstract:
...: validator = "Foo"
...: username = f"The {validator} username"

In [2]: Abstract().username
Out[2]: 'The Foo username'

In [3]: class MyClass(Abstract):
...: validator = "Bar"

In [4]: MyClass().username
Out[4]: 'The Foo username'
}}}

In this example, the class attribute `username` is defined (and
"calculated") at class definition time and is not something "dynamic" that
you can expect it to be "recalculated" in children, if you don't override
it.

Having said the above, please also note that
[https://docs.djangoproject.com/en/dev/topics/auth/customizing/ the user
customization docs] indicate that if you wish to customize the `User`
model, ideally you would extend `AbstractBaseUser`.
[https://docs.djangoproject.com/en/dev/topics/auth/customizing/#extending-
django-s-default-user Specifically AbstractUser should be used when adding
more fiels, not changing existing fields behavior]:

> If you’re entirely happy with Django’s User model, but you want to add
some additional profile information, you could subclass
django.contrib.auth.models.AbstractUser and add your custom profile
fields, although we’d recommend a separate model as described in
Specifying a custom user model.

So this means that if you are extending `AbstractUser`, the default
username validation should suffice for your case. If it does not suffice,
then perhaps you should consider extending `AbstractBaseUser` and building
your own validator and custom username field as your business logic
requires.

Because of the above, this report seems better suited to be a support
request. The best place to get more answers to your issue is using any of
the user support channels from
[https://docs.djangoproject.com/en/dev/faq/help/#how-do-i-do-x-why-
doesn-t-y-work-where-can-i-go-to-get-help this link]. Since the goal of
this issue tracker is to track issues about Django itself, and your issue
seems, at first, to be located in your custom code, I'll be closing this
ticket as invalid following the
[https://docs.djangoproject.com/en/dev/internals/contributing/triaging-
tickets/#closing-tickets ticket triaging process].
--
Ticket URL: <https://code.djangoproject.com/ticket/35578#comment:1>
Reply all
Reply to author
Forward
0 new messages