[Django] #32396: UsernameField normalisation throws TypeError if the username is empty

20 views
Skip to first unread message

Django

unread,
Jan 29, 2021, 5:12:07 PM1/29/21
to django-...@googlegroups.com
#32396: UsernameField normalisation throws TypeError if the username is empty
----------------------------------------+------------------------
Reporter: Łukasz Rzepa | Owner: nobody
Type: Bug | Status: new
Component: contrib.auth | Version: 3.1
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 guys, this is my first ticket so excuse me if it's not perfect.

I'm working on a project where we use custom `User` using `email` as a
`USERNAME_FIELD`. We allow users to have custom usernames but we don't
require them so `username` field has `null=True`.

While editing one of the staff users through the admin panel I've stumbled
upon an error when leaving the `username` field empty:

{{{
TypeError
normalize() argument 2 must be str, not None
}}}

To register `User` model to admin I'm using:

{{{
@admin.register(User)
class UserAdminView(UserAdmin):
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2'),
}),
)
}}}

The source of the problem is the fact that `unicodedata.normalize()` in

{{{
class UsernameField(forms.CharField):
def to_python(self, value):
return unicodedata.normalize('NFKC', super().to_python(value))
}}}

needs a second argument to be a string. As `super().to_python(value)` is
actually `forms.CharField.to_python()` `''` value is returned as
`self.empty_value` with defaults to `''` but for a situation where
`CharField` has `null=True`. In this case it's determined in
`django.db.models.fields.CharField.formfield()` that

{{{
if self.null and not
connection.features.interprets_empty_strings_as_nulls:
defaults['empty_value'] = None
}}}

and our `self.empty_value` becomes `None` which is in effect passed to
normalize as a second argument.

My proposition is to fix it like this:

{{{
class UsernameField(forms.CharField):
def to_python(self, value):
value = super().to_python(value)
return None if value is None else unicodedata.normalize('NFKC',
value)
}}}

and allow the field null condition to be validated on the `model` level.


If you find this fix reasonable I'd be happy to open a PR with the
suggested change.


My project is using Django 2.2 but it's the same for 3.1.

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

Django

unread,
Jan 29, 2021, 5:16:59 PM1/29/21
to django-...@googlegroups.com
#32396: UsernameField normalisation throws TypeError if the username is empty
------------------------------+----------------------------------------
Reporter: Łukasz Rzepa | Owner: Łukasz Rzepa
Type: Bug | Status: assigned
Component: contrib.auth | Version: 3.1
Severity: Normal | Resolution:

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 Łukasz Rzepa):

* owner: nobody => Łukasz Rzepa
* status: new => assigned


--
Ticket URL: <https://code.djangoproject.com/ticket/32396#comment:1>

Django

unread,
Feb 1, 2021, 4:14:27 AM2/1/21
to django-...@googlegroups.com
#32396: UsernameField normalisation throws TypeError if the username is empty
------------------------------+--------------------------------------
Reporter: Łukasz Rzepa | Owner: (none)

Type: Bug | Status: new
Component: contrib.auth | Version: 3.1
Severity: Normal | Resolution:

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 Łukasz Rzepa):

* owner: Łukasz Rzepa => (none)
* status: assigned => new


--
Ticket URL: <https://code.djangoproject.com/ticket/32396#comment:2>

Django

unread,
Feb 2, 2021, 3:56:26 AM2/2/21
to django-...@googlegroups.com
#32396: UsernameField normalisation throws TypeError if the username is empty
------------------------------+--------------------------------------
Reporter: Łukasz Rzepa | Owner: (none)
Type: Bug | Status: closed
Component: contrib.auth | Version: 3.1
Severity: Normal | Resolution: duplicate

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 Carlton Gibson):

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


Comment:

Hi, thanks for the report — nice and clear.

I'm going to close this as a duplicate of #31972. As per the docs on
[https://docs.djangoproject.com/en/3.1/topics/auth/customizing/#custom-
users-and-the-built-in-auth-forms Custom users and the built-in auth
forms] you'll need to extend or customise the forms here. (Using
[https://docs.djangoproject.com/en/3.1/ref/contrib/admin/#django.contrib.admin.ModelAdmin.get_form
`ModelAdmin.get_form()`] I imagine.)

--
Ticket URL: <https://code.djangoproject.com/ticket/32396#comment:3>

Reply all
Reply to author
Forward
0 new messages