#29449: Regression in UserCreationForm (and UserChangeForm) for custom user 
models
-------------------------------------+-------------------------------------
               Reporter:  Sławek     |          Owner:  nobody
  Ehlert                             |
                   Type:  Bug        |         Status:  new
              Component:             |        Version:  2.1
  contrib.auth                       |       Keywords:  auth forms
               Severity:  Normal     |  UserCreationForm UserChangeForm
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 In 3333d935d2914cd80cf31f4803821ad5c0e2a51d (part of #28757 ticket)
 {{{UserCreationForm}}} (and by extension also {{{UserChangeForm}}}) was
 adjusted to support custom user models without overriding the form. The
 problem is that the implementation there assumes that the
 {{{USERNAME_FIELD}}} has to be a subclass of {{{CharField}}} since it uses
 {{{UsernameField}}} in the {{{field_classes}}} mapping.

 Now to the fun part. Django already has some tests that should fail in
 such case (for example see
 
https://github.com/django/django/blob/825f0beda804e48e9197fcf3b0d909f9f548aa47/tests/auth_tests/test_management.py#L435-L491),
 but the failure is actually "swallowed" when running the whole test suite.
 When running those tests individually we can see the failure.
 Tim Graham already noticed something similar in
 https://code.djangoproject.com/ticket/28757#comment:7.
 I.e.
 {{{
  ./runtests.py auth_tests
 }}}
 works, but
 {{{
 ./runtests.py
 
auth_tests.test_management.CreatesuperuserManagementCommandTestCase.test_fields_with_fk
 }}}
 doesn't. I'm not sure why the failure is hidden in the former case (I
 suspect it has to do something with the {{{override_settings}}} decorator
 and {{{importlib.reload}}}ing done in the {{{reload_auth_forms}}} function
 from the commit I've mentioned). The stacktrace from the latter case looks
 like this:
 {{{
 ERROR: test_fields_with_fk
 (auth_tests.test_management.CreatesuperuserManagementCommandTestCase)
 ----------------------------------------------------------------------
 Traceback (most recent call last):
   File "/Users/slafs/testing/django/django/django/test/utils.py", line
 364, in inner
     with self as context:
   File "/Users/slafs/testing/django/django/django/test/utils.py", line
 336, in __enter__
     return self.enable()
   File "/Users/slafs/testing/django/django/django/test/utils.py", line
 405, in enable
     setting=key, value=new_value, enter=True)
   File "/Users/slafs/testing/django/django/django/dispatch/dispatcher.py",
 line 175, in send
     for receiver in self._live_receivers(sender)
   File "/Users/slafs/testing/django/django/django/dispatch/dispatcher.py",
 line 175, in <listcomp>
     for receiver in self._live_receivers(sender)
   File "/Users/slafs/testing/django/django/django/test/signals.py", line
 195, in user_model_swapped
     from django.contrib.auth import forms
   File "/Users/slafs/testing/django/django/django/contrib/auth/forms.py",
 line 63, in <module>
     class UserCreationForm(forms.ModelForm):
   File "/Users/slafs/testing/django/django/django/forms/models.py", line
 256, in __new__
     apply_limit_choices_to=False,
   File "/Users/slafs/testing/django/django/django/forms/models.py", line
 172, in fields_for_model
     formfield = f.formfield(**kwargs)
   File
 "/Users/slafs/testing/django/django/django/db/models/fields/related.py",
 line 956, in formfield
     **kwargs,
   File
 "/Users/slafs/testing/django/django/django/db/models/fields/related.py",
 line 418, in formfield
     return super().formfield(**defaults)
   File
 "/Users/slafs/testing/django/django/django/db/models/fields/__init__.py",
 line 890, in formfield
     return form_class(**defaults)
   File "/Users/slafs/testing/django/django/django/forms/fields.py", line
 213, in __init__
     super().__init__(**kwargs)
 TypeError: __init__() got an unexpected keyword argument
 'limit_choices_to'
 }}}

 Since {{{auth_tests.CustomUserWithFK}}} model uses a {{{ForeignKey}}} as a
 {{{USERNAME_FIELD}}}, the instantiation of
 {{{django.contrib.auth.forms.UsernameField}}} is failing. However, that
 test is a bit implicit as I'm not entirely sure why Django imports
 {{{UserCreationForm}}} in the first place (the stacktrace makes me think
 it's because of the signal mechanisms).

 I'd suggest the following steps to go forward with this:

 1) Write a more explicit regression test in {{{auth_tests.test_forms}}}
 that's using {{{auth_tests.CustomUserWithFK}}} as a user model (I'll try
 to do that).
 2) Make adjustments in {{{auth_tests.test_forms}}} so that the mentioned
 tests will actually fail even when running the whole test suite (I think
 Tim Graham already tried this in
 https://code.djangoproject.com/ticket/28757#comment:8).
 3) Fix {{{UserCreationForm}}} so it supports different types of fields for
 {{{USERNAME_FIELD}}}.

 In my humble opinion this is a release blocker (I haven't marked this
 ticket as such, though).

-- 
Ticket URL: <https://code.djangoproject.com/ticket/29449>
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/048.48dcf8393a8a7281a77ca9dd8f3cc022%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to