{{{
from uuid import uuid4
from django.contrib.auth.models import AbstractUser
from django.db import models
class Company(models.Model):
name = models.CharField(max_length=64, primary_key=True)
class User(AbstractUser):
uuid = models.UUIDField(primary_key=True, editable=False,
default=uuid4)
company = models.ForeignKey(Company)
REQUIRED_FIELDS = ['email', 'company']
}}}
When I run `manage.py createsuperuser` I got this result:
{{{
Username: superuser
Email address: te...@example.com
Company (Company.name): TEST
Password:
Password (again):
Traceback (most recent call last):
File "manage.py", line 22, in <module>
execute_from_command_line(sys.argv)
File "/Users/ookami/venv/swportal/lib/python3.5/site-
packages/django/core/management/__init__.py", line 363, in
execute_from_command_line
utility.execute()
File "/Users/ookami/venv/swportal/lib/python3.5/site-
packages/django/core/management/__init__.py", line 355, in execute
self.fetch_command(subcommand).run_from_argv(self.argv)
File "/Users/ookami/venv/swportal/lib/python3.5/site-
packages/django/core/management/base.py", line 283, in run_from_argv
self.execute(*args, **cmd_options)
File "/Users/ookami/venv/swportal/lib/python3.5/site-
packages/django/contrib/auth/management/commands/createsuperuser.py", line
63, in execute
return super(Command, self).execute(*args, **options)
File "/Users/ookami/venv/swportal/lib/python3.5/site-
packages/django/core/management/base.py", line 330, in execute
output = self.handle(*args, **options)
File "/Users/ookami/venv/swportal/lib/python3.5/site-
packages/django/contrib/auth/management/commands/createsuperuser.py", line
183, in handle
self.UserModel._default_manager.db_manager(database).create_superuser(**user_data)
File "/Users/ookami/venv/swportal/lib/python3.5/site-
packages/django/contrib/auth/models.py", line 170, in create_superuser
return self._create_user(username, email, password, **extra_fields)
File "/Users/ookami/venv/swportal/lib/python3.5/site-
packages/django/contrib/auth/models.py", line 151, in _create_user
user = self.model(username=username, email=email, **extra_fields)
File "/Users/ookami/venv/swportal/lib/python3.5/site-
packages/django/contrib/auth/base_user.py", line 68, in __init__
super(AbstractBaseUser, self).__init__(*args, **kwargs)
File "/Users/ookami/venv/swportal/lib/python3.5/site-
packages/django/db/models/base.py", line 554, in __init__
_setattr(self, field.name, rel_obj)
File "/Users/ookami/venv/swportal/lib/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 "'TEST'": "User.company" must be a "Company"
instance.
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/28461>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* Attachment "local_history.patch" added.
Possible solution
* has_patch: 0 => 1
--
Ticket URL: <https://code.djangoproject.com/ticket/28461#comment:1>
* needs_better_patch: 0 => 1
* stage: Unreviewed => Accepted
Comment:
I can reproduce the crash, however, the proposed patch breaks the
`test_fields_with_fk_interactive` test from #21832.
--
Ticket URL: <https://code.djangoproject.com/ticket/28461#comment:2>
--
Ticket URL: <https://code.djangoproject.com/ticket/28461#comment:3>
* needs_better_patch: 1 => 0
* has_patch: 1 => 0
Old description:
New description:
These are my models:
{{{
from uuid import uuid4
}}}
[https://github.com/django/django/pull/8846 PR]
--
--
Ticket URL: <https://code.djangoproject.com/ticket/28461#comment:4>
Comment (by Kirill B.):
The problem is not in CharField – actually any ForeignKey will fail.
Current tests are using customized UserManager, where ForeignKey is
resolved manually. I've created new test where custom user is inherited
from default User model.
I've created PR with my proposal to fix this problem.
--
Ticket URL: <https://code.djangoproject.com/ticket/28461#comment:5>
* has_patch: 0 => 1
--
Ticket URL: <https://code.djangoproject.com/ticket/28461#comment:6>
Comment (by Tim Graham):
Do you see a downside to documenting that `UserManager.create_superuser()`
must be implemented as it is now in the tests? The proposed change will
break currently working code (as the change in
`CustomUserWithFKManager.create_superuser()` demonstrates).
--
Ticket URL: <https://code.djangoproject.com/ticket/28461#comment:7>
Comment (by Kirill B.):
Yeah, I think this moment should be clarified in docs, but I'm in doubt
what exactly should go there.
I guess there are 2 places where this can be described: `createsuperuser`
management command docs and `models.CustomUserManager.create_superuser`
section in `auth/customizing.txt`.
--
Ticket URL: <https://code.djangoproject.com/ticket/28461#comment:8>
* type: Bug => Cleanup/optimization
* has_patch: 1 => 0
* component: contrib.auth => Documentation
Comment:
I think I'd put a note in `UserManager.create_superuser()` as you
mentioned and also in the docs for `REQUIRED_FIELDS`
in`topics/auth/customizing.txt`. In the latter place, there's already a
note there about `ForeignKey` that could be elaborated upon.
--
Ticket URL: <https://code.djangoproject.com/ticket/28461#comment:9>
Comment (by Kirill B.):
I thought you meant to update documentation in addition to this change.
The problem is that the current implementation of `createsuperuser`
management command doesn't work with the default implementation of
UserManager (see the code in my first post). So either the implementation
of default `UserManager.create_superuser()` or `createsuperuser`
management command should be changed.
--
Ticket URL: <https://code.djangoproject.com/ticket/28461#comment:10>
Comment (by Tim Graham):
I understand your point and am not completely convinced about which way to
go, however, technically, I think your code doesn't conform to
[https://docs.djangoproject.com/en/stable/topics/auth/customizing/#django.contrib.auth.models.AbstractUser
the documentation] which says:
If your user model defines [the same fields] as Django’s default user,
you can just install Django’s `UserManager`; however, if your user model
defines different fields, you’ll need to define a custom manager that
extends `BaseUserManager` providing two additional methods:
...
The prototype of `create_superuser()` should accept the username field,
plus all required fields as arguments.
Since you added `'company'` in `REQUIRED_FIELDS`, the documentation
suggests that a custom manager must be added for this situation.
--
Ticket URL: <https://code.djangoproject.com/ticket/28461#comment:11>