title: Django error admin.E033: username is not an attribute of users.CustomUser. Why is my custom user admin not working?
body: <p>I am creating a custom user model in Django. I have defined a custom user model (users.CustomUser) which subclasses AbstractBaseUser. I have created a custom user manager (users.CustomUserManager) which subclasses BaseUserManager and works properly. I have also created a custom user admin which subclasses UserAdmin since my CustomUser model does not have a username field (it uses 'email' instead).</p>
  
  <p>As far as I can tell, I have coded everything properly, but when I run 'python manage.py makemigrations' I get an error message: </p>
  
  <pre><code>&lt;class 'users.admin.CustomUserAdmin'&gt;: (admin.E033) The value of 'ordering[0]' refers to 'username', which is not an attribute of 'users.CustomUser'.
  </code></pre>
  
  <p>I'm stuck here.</p>
  
  <p>I have already tried the following:
  (1) Defined username field to be email in my custom user model class
  (2) Tried setting username to None in my custom user model class and custom user admin
  (3) Created custom user registration and change forms and registered them with my custom user admin</p>
  
  <pre class="lang-py prettyprint-override"><code># models.py
  from django.db import models
  from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
  from phonenumber_field.modelfields import PhoneNumberField
  from .managers import CustomUserManager
  
  class CustomUser(AbstractBaseUser, PermissionsMixin):
      username = None
      firstname = models.CharField(max_length = 60)
      lastname = models.CharField(max_length = 60)
      email = models.EmailField(max_length = 240, unique=True)
      phone = PhoneNumberField(null=True, blank=True)
      company = models.ForeignKey(Company, on_delete=models.CASCADE, null=True, blank=True)
      password = models.CharField(max_length = 240)
  
      USERNAME_FIELD = 'email'
      REQUIRED_FIELDS = ['firstname', 'lastname', 'company', 'password']
  
      objects = CustomUserManager()
  
      def __str__(self):
          return self.email
  </code></pre>
  
  <pre class="lang-py prettyprint-override"><code># managers.py
  from django.contrib.auth.base_user import BaseUserManager
  
  class CustomUserManager(BaseUserManager):
      def create_user(self, email, firstname, lastname, company, password, **extra_fields):
          email = self.normalize_email(email)
          user = self.model(
              email=email,
              firstname=firstname,
              lastname=lastname,
              company=company,
              **extra_fields
          )
          user.set_password(password)
          user.save()
          return user
  </code></pre>
  
  <pre class="lang-py prettyprint-override"><code>#forms.py
  from django.contrib.auth.models import User
  from django import forms
  from django.contrib.auth.forms import UserCreationForm, UserChangeForm
  from .models import CustomUser, Company
  from phonenumber_field.modelfields import PhoneNumberField
  from django.core.exceptions import ValidationError
  
  class CustomUserRegistrationForm(forms.ModelForm):
      firstname = forms.CharField(label = 'First Name*', max_length = 120)
      lastname = forms.CharField(label = 'Last Name*', max_length = 120)
      email = forms.EmailField(label = 'Email*')
      phone = PhoneNumberField()
      company = forms.ModelChoiceField(queryset = Company.objects.all(), label = 'Company*', required = True)
      password = forms.CharField(label = 'Password*', min_length = 5, max_length = 50, widget = forms.PasswordInput)
      password2 = forms.CharField(label = 'Confirm Password*', min_length = 5, max_length = 50, widget = forms.PasswordInput)
  
      class Meta:
          model = CustomUser
          fields = ('firstname', 'lastname', 'company', 'email', 'phone', 'password')
  
      def clean_email(self):
          email = self.cleaned_data['email'].lower()
          user_list = CustomUser.objects.filter(email=email)
          if user_list.count():
              raise ValidationError('There is already an account associated with that email.')
          return email
  
      def clean_password2(self):
          password1 = self.cleaned_data['password']
          password2 = self.cleaned_data['password2']
  
          if (password1 and password2) and (password1 != password2):
              raise ValidationError('Passwords do not match.')
          return password2
  
      def save(self, commit=True):
          context = {
              'firstname':self.cleaned_data['firstname'],
              'lastname':self.cleaned_data['lastname'],
              'email':self.cleaned_data['email'],
              'phone':self.cleaned_data['phone'],
              'password':self.cleaned_data['password'],
              'admin':'',
              'company':self.cleaned_data['company'],
          }
          custom_user = CustomUser.objects.create_user(
              context['email'],
              context['firstname'],
              context['lastname'],
              context['company'],
              context['password']
          )
          return custom_user
  
  class CustomUserChangeForm(UserChangeForm):
      firstname = forms.CharField(label = 'First Name', max_length = 120)
      lastname = forms.CharField(label = 'Last Name', max_length = 120)
      email = forms.EmailField(label = 'New Email')
      phone = PhoneNumberField()
      old_password = forms.CharField(label = 'Current Password', min_length = 5, max_length = 50, widget = forms.PasswordInput)
      new_password = forms.CharField(label = 'New Password', min_length = 5, max_length = 50, widget = forms.PasswordInput)
      new_password2 = forms.CharField(label = 'Confirm New Password', min_length = 5, max_length = 50, widget = forms.PasswordInput)
  
      class Meta:
          model = CustomUser
          exclude = ['company',]
  
      def clean_new_password(self):
          new_password = self.cleaned_data['new_password']
          new_password2 = self.cleaned_data['new_password2']
          if (new_password and new_password2) and (new_password != new_password2):
              raise ValidationError('Passwords do not match.')
          if not (new_password and new_password2):
              raise ValidationError('Please enter new password twice.')
  
          return new_password
  
      def clean_email(self):
          email = self.cleaned_data['email']
          email_list = CustomUser.objects.filter(email=email)
          if email_list.count():
              raise ValidationError('There is already an account associated with that email.')
  
          return email
  </code></pre>
  
  <pre class="lang-py prettyprint-override"><code># admin.py
  from django.contrib import admin
  from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
  from .models import CustomUser
  from .forms import CustomUserRegistrationForm, CustomUserChangeForm
  
  class CustomUserAdmin(BaseUserAdmin):
      add_form = CustomUserRegistrationForm
      form = CustomUserChangeForm
      model = CustomUser
  
      list_display = ('firstname', 'lastname', 'email', 'company')
      list_filter = ('company',)
      fieldsets = (
          (None, {'fields': ('email', 'old_password', 'new_password', 'new_password2')}),
          ('Personal Information', {'fields': ('firstname', 'lastname', 'phone')}),
      )
      add_fieldsets = (
          (None, {'fields': ('email', 'password', 'password2')}),
          ('Personal Information', {'fields': ('firstname', 'lastname', 'phone')}),
          ('Company Information', {'fields': ('company',)}),
      )
  
  admin.site.register(CustomUser, CustomUserAdmin)
  </code></pre>
  
  <p>I expect to be able to migrate the database properly and use my custom user model on my site (i.e. allow users to sign up and create profiles using the custom fields I have outlined). Instead, when trying to run migrations
  in the Command Prompt, I get the error shown above.</p>
  
  <p>Any help is appreciated! Thanks!</p>