﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
32396	UsernameField normalisation throws TypeError if the username is empty	Łukasz Rzepa		"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."	Bug	closed	contrib.auth	3.1	Normal	duplicate			Unreviewed	0	0	0	0	0	0
