createsuperuser gives KeyError after implementing custom user

Question:

Hey I’m fairly new to Django and I’m trying to setup a pretty basic rest API. I am using djoser to handle authentication. However I want to use a custom user model. Where 1. the unique field is the email (instead of username) and 2. it is has one extra field.

I tried to follow these two guides,

https://testdriven.io/blog/django-custom-user-model/
(To use email instead of username)

https://simpleisbetterthancomplex.com/tutorial/2016/07/22/how-to-extend-django-user-model.html#abstractuser (To extend the usermodel)

I create the model like so,

class MyUser(AbstractUser):
    username = None
    email = models.EmailField(_('email address'), unique=True)
    
    DIET_CHOICES = (
        ('vegan', 'Vegan'),
        ('vegetarian', 'Vegetarian'),
        ('meat', 'Meat')
    )

    diet = models.CharField(max_length=10, choices=DIET_CHOICES)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = [diet]

    objects = CustomUserManager()

    def __str__(self):
        return self.email

Using the CustomUserManager() as shown in https://testdriven.io/blog/django-custom-user-model/.

I have also registered the user in AUTH_USER_MODEL.
Looking at the migration file I get what I expect. But after migrating when I then try to run createsuperuser, it instantly results in the following error

Traceback (most recent call last):
  File "/home/frederik/Documents/andet/madklubTests/2madklubDjango/venv/lib/python3.9/site-packages/django/db/models/options.py", line 672, in get_field
    return self.fields_map[field_name]
KeyError: <django.db.models.fields.CharField: diet>

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/frederik/Documents/andet/madklubTests/2madklubDjango/manage.py", line 22, in <module>
    main()
  File "/home/frederik/Documents/andet/madklubTests/2madklubDjango/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/home/frederik/Documents/andet/madklubTests/2madklubDjango/venv/lib/python3.9/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "/home/frederik/Documents/andet/madklubTests/2madklubDjango/venv/lib/python3.9/site-packages/django/core/management/__init__.py", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/home/frederik/Documents/andet/madklubTests/2madklubDjango/venv/lib/python3.9/site-packages/django/core/management/base.py", line 406, in run_from_argv
    parser = self.create_parser(argv[0], argv[1])
  File "/home/frederik/Documents/andet/madklubTests/2madklubDjango/venv/lib/python3.9/site-packages/django/core/management/base.py", line 369, in create_parser
    self.add_arguments(parser)
  File "/home/frederik/Documents/andet/madklubTests/2madklubDjango/venv/lib/python3.9/site-packages/django/contrib/auth/management/commands/createsuperuser.py", line 60, in add_arguments
    field = self.UserModel._meta.get_field(field_name)
  File "/home/frederik/Documents/andet/madklubTests/2madklubDjango/venv/lib/python3.9/site-packages/django/db/models/options.py", line 674, in get_field
    raise FieldDoesNotExist(
django.core.exceptions.FieldDoesNotExist: MyUser has no field named 'MyUser.MyUser.diet'

It seems that it might not be a specific problem to createsuperuser, but rather a problem in general with user registration. However I am not sure why this happens.

Asked By: wardz

||

Answers:

Replace

REQUIRED_FIELDS = [diet]

with

REQUIRED_FIELDS = ['diet']

You should put name of field instead of itself.

Answered By: Sajjad Sanikhani

You specify the required fields as names, so strings that contain the names of the fields.

Yes, I thought this might be the problem, but not sure why? How would I then go about creating a required field in my model? Say I want diet, first_name, last_name to be required?

Then you create a list of strings with these names, so:

class MyUser(AbstractUser):
    username = None
    email = models.EmailField(_('email address'), unique=True)
    
    DIET_CHOICES = (
        ('vegan', 'Vegan'),
        ('vegetarian', 'Vegetarian'),
        ('meat', 'Meat')
    )

    diet = models.CharField(max_length=10, choices=DIET_CHOICES)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['first_name', 'last_name', 'diet']

    objects = CustomUserManager()

    def __str__(self):
        return self.email
Answered By: Willem Van Onsem