#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 django-updates+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/047.d3fc71b935236cb83accf834f6595f73%40djangoproject.com.

Reply via email to