#28594: Value error on related user name during save of user model
-------------------------------------+-------------------------------------
     Reporter:  Axel Rau             |                    Owner:  nobody
         Type:  Bug                  |                   Status:  new
    Component:  contrib.auth         |                  Version:  1.11
     Severity:  Normal               |               Resolution:
     Keywords:  Value error, user    |             Triage Stage:
  model, normalize_username          |  Unreviewed
    Has patch:  0                    |      Needs documentation:  0
  Needs tests:  0                    |  Patch needs improvement:  0
Easy pickings:  0                    |                    UI/UX:  0
-------------------------------------+-------------------------------------

Old description:

> problem:
> While upgrading from 1.9 to 1.11, ForwardManyToOneDescriptor.__set__()
> tries to assign a string (description of the related instance) to the
> related user name field
> of user model.
> diagnosis:
> In 1.10 normalize_username(), a class method of AbstractBaseUser, has
> been introduced.
> This class method forces the related user name instance to a string.
> Fix:
> Overwriting this with a method which just returns the 'username' fixes
> the problem.
>
> Details:
>
> class AbstractEmailUser(AbstractBaseUser, PermissionsMixin,
> FieldlistForDetailTemplateMixin):
>    localemail = models.OneToOneField('Mailbox', verbose_name=_('Local
> E-mail'),
>            related_name='localemail', db_column='localemail',
>            editable=('UR', 'UE', 'UL'))
>
>    objects = UserManager()
>
>    USERNAME_FIELD = 'localemail'
>    REQUIRED_FIELDS = []
>
>    class Meta:
>        abstract = True
>        ordering = ['localemail']
>
>    def get_username(self):
>       return getattr(self, self.USERNAME_FIELD)
>
> class Mailbox(models.Model):
>    id = models.AutoField(primary_key=True)
>    localpart = models.CharField(_('Localpart'), max_length=40)
>    localdomainfk = models.ForeignKey(Localdomain,
> verbose_name=_('Domain'), db_column='localdomainfk', editable=('AL',))
>         …
>
>    def __str__(self):
>         return self.localpart+ '@'+self.localdomainfk.name
>

> Internal Server Error: /admin/erdb/account/19/change/
> Traceback (most recent call last):
>  File "...python3.5/site-packages/django/core/handlers/exception.py",
> line 41, in inner
>    response = get_response(request)
>  File "...python3.5/site-packages/django/core/handlers/base.py", line
> 249, in _legacy_get_response
>    response = self._get_response(request)
>  File "...python3.5/site-packages/django/core/handlers/base.py", line
> 187, in _get_response
>    response = self.process_exception_by_middleware(e, request)
>  File "...python3.5/site-packages/django/core/handlers/base.py", line
> 185, in _get_response
>    response = wrapped_callback(request, *callback_args,
> **callback_kwargs)
>  File
> "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/contextlib.py",
> line 30, in inner
>    return func(*args, **kwds)
>  File "...python3.5/site-packages/django/contrib/admin/options.py", line
> 551, in wrapper
>    return self.admin_site.admin_view(view)(*args, **kwargs)
>  File "...python3.5/site-packages/django/utils/decorators.py", line 149,
> in _wrapped_view
>    response = view_func(request, *args, **kwargs)
>  File "...python3.5/site-packages/django/views/decorators/cache.py", line
> 57, in _wrapped_view_func
>    response = view_func(request, *args, **kwargs)
>  File "...python3.5/site-packages/django/contrib/admin/sites.py", line
> 224, in inner
>    return view(request, *args, **kwargs)
>  File "...python3.5/site-packages/django/contrib/admin/options.py", line
> 1511, in change_view
>    return self.changeform_view(request, object_id, form_url,
> extra_context)
>  File "...python3.5/site-packages/django/utils/decorators.py", line 67,
> in _wrapper
>    return bound_func(*args, **kwargs)
>  File "...python3.5/site-packages/django/utils/decorators.py", line 149,
> in _wrapped_view
>    response = view_func(request, *args, **kwargs)
>  File "...python3.5/site-packages/django/utils/decorators.py", line 63,
> in bound_func
>    return func.__get__(self, type(self))(*args2, **kwargs2)
>  File "...python3.5/site-packages/django/contrib/admin/options.py", line
> 1408, in changeform_view
>    return self._changeform_view(request, object_id, form_url,
> extra_context)
>  File "...python3.5/site-packages/django/contrib/admin/options.py", line
> 1440, in _changeform_view
>    if form.is_valid():
>  File "...python3.5/site-packages/django/forms/forms.py", line 183, in
> is_valid
>    return self.is_bound and not self.errors
>  File "...python3.5/site-packages/django/forms/forms.py", line 175, in
> errors
>    self.full_clean()
>  File "...python3.5/site-packages/django/forms/forms.py", line 386, in
> full_clean
>    self._post_clean()
>  File "...python3.5/site-packages/django/forms/models.py", line 408, in
> _post_clean
>    self.instance.full_clean(exclude=exclude, validate_unique=False)
>  File "...python3.5/site-packages/django/db/models/base.py", line 1234,
> in full_clean
>    self.clean()
>  File "...python3.5/site-packages/django/contrib/auth/base_user.py", line
> 77, in clean
>    setattr(self, self.USERNAME_FIELD,
> self.normalize_username(self.get_username()))
>  File "...python3.5/site-
> packages/django/db/models/fields/related_descriptors.py", line 216, in
> __set__
>    self.field.remote_field.model._meta.object_name,
> ValueError: Cannot assign "'[email protected]'": "Account.localemail"
> must be a "Mailbox" instance.
> [21/Aug/2017 16:08:37] "POST /admin/erdb/account/19/change/ HTTP/1.1" 500
> 166385
>
> Discussion:
> https://www.mail-archive.com/[email protected]/msg178769.html

New description:

 problem:
 While upgrading from 1.9 to 1.11, `ForwardManyToOneDescriptor.__set__()`
 tries to assign a string (description of the related instance) to the
 related user name field of user model.
 diagnosis:
 In 1.10 `normalize_username()`, a class method of `AbstractBaseUser`, has
 been introduced. This class method forces the related user name instance
 to a string.
 Fix:
 Overwriting this with a method which just returns the 'username' fixes the
 problem.

 Details:
 {{{
 class AbstractEmailUser(AbstractBaseUser, PermissionsMixin,
 FieldlistForDetailTemplateMixin):
    localemail = models.OneToOneField('Mailbox', verbose_name=_('Local
 E-mail'),
            related_name='localemail', db_column='localemail',
            editable=('UR', 'UE', 'UL'))

    objects = UserManager()

    USERNAME_FIELD = 'localemail'
    REQUIRED_FIELDS = []

    class Meta:
        abstract = True
        ordering = ['localemail']

    def get_username(self):
       return getattr(self, self.USERNAME_FIELD)

 class Mailbox(models.Model):
    id = models.AutoField(primary_key=True)
    localpart = models.CharField(_('Localpart'), max_length=40)
    localdomainfk = models.ForeignKey(Localdomain,
 verbose_name=_('Domain'), db_column='localdomainfk', editable=('AL',))
         …

    def __str__(self):
         return self.localpart+ '@'+self.localdomainfk.name


 Internal Server Error: /admin/erdb/account/19/change/
 Traceback (most recent call last):
  File "...python3.5/site-packages/django/core/handlers/exception.py", line
 41, in inner
    response = get_response(request)
  File "...python3.5/site-packages/django/core/handlers/base.py", line 249,
 in _legacy_get_response
    response = self._get_response(request)
  File "...python3.5/site-packages/django/core/handlers/base.py", line 187,
 in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "...python3.5/site-packages/django/core/handlers/base.py", line 185,
 in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File
 
"/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/contextlib.py",
 line 30, in inner
    return func(*args, **kwds)
  File "...python3.5/site-packages/django/contrib/admin/options.py", line
 551, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
  File "...python3.5/site-packages/django/utils/decorators.py", line 149,
 in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "...python3.5/site-packages/django/views/decorators/cache.py", line
 57, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "...python3.5/site-packages/django/contrib/admin/sites.py", line
 224, in inner
    return view(request, *args, **kwargs)
  File "...python3.5/site-packages/django/contrib/admin/options.py", line
 1511, in change_view
    return self.changeform_view(request, object_id, form_url,
 extra_context)
  File "...python3.5/site-packages/django/utils/decorators.py", line 67, in
 _wrapper
    return bound_func(*args, **kwargs)
  File "...python3.5/site-packages/django/utils/decorators.py", line 149,
 in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "...python3.5/site-packages/django/utils/decorators.py", line 63, in
 bound_func
    return func.__get__(self, type(self))(*args2, **kwargs2)
  File "...python3.5/site-packages/django/contrib/admin/options.py", line
 1408, in changeform_view
    return self._changeform_view(request, object_id, form_url,
 extra_context)
  File "...python3.5/site-packages/django/contrib/admin/options.py", line
 1440, in _changeform_view
    if form.is_valid():
  File "...python3.5/site-packages/django/forms/forms.py", line 183, in
 is_valid
    return self.is_bound and not self.errors
  File "...python3.5/site-packages/django/forms/forms.py", line 175, in
 errors
    self.full_clean()
  File "...python3.5/site-packages/django/forms/forms.py", line 386, in
 full_clean
    self._post_clean()
  File "...python3.5/site-packages/django/forms/models.py", line 408, in
 _post_clean
    self.instance.full_clean(exclude=exclude, validate_unique=False)
  File "...python3.5/site-packages/django/db/models/base.py", line 1234, in
 full_clean
    self.clean()
  File "...python3.5/site-packages/django/contrib/auth/base_user.py", line
 77, in clean
    setattr(self, self.USERNAME_FIELD,
 self.normalize_username(self.get_username()))
  File "...python3.5/site-
 packages/django/db/models/fields/related_descriptors.py", line 216, in
 __set__
    self.field.remote_field.model._meta.object_name,
 ValueError: Cannot assign "'[email protected]'": "Account.localemail"
 must be a "Mailbox" instance.
 [21/Aug/2017 16:08:37] "POST /admin/erdb/account/19/change/ HTTP/1.1" 500
 166385
 }}}
 Discussion:
 https://www.mail-archive.com/[email protected]/msg178769.html

--

Comment (by Tim Graham):

 Can you propose a patch for Django?

-- 
Ticket URL: <https://code.djangoproject.com/ticket/28594#comment:1>
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 post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/061.d15734bd6b645ec07694f657d8a78ccc%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to