#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.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/047.d3fc71b935236cb83accf834f6595f73%40djangoproject.com.

Reply via email to