VnC
VnC

Reputation: 2016

Django create CustomUser model

Folks,

I'm trying to create my own User model by extending the AbstractBaseUser model provided by Django.

However, I keep on getting the following error when migrating: ValueError: The field admin.LogEntry.user was declared with a lazy reference to '<app_name>.user', but app '<app_name>' doesn't provide model 'user'.

What I have done so far is the following:

In app/models.py added CustomUser class together with CustomUserManager with relevant fields and all.

In app/admin.py I've added this:

from django.contrib.auth import get_user_model
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserCreationForm, UserChangeForm

from <app_name>.models import CustomUser


class CustomUserChangeForm(UserChangeForm):

    class Meta:
        model = get_user_model()
        fields = ('email',)

class CustomUserCreationForm(UserCreationForm):

    class Meta:
        model = get_user_model()
        fields = ('email',)

    def clean_username(self):
        username = self.cleaned_data["username"]
        try:
            get_user_model().objects.get(username=username)
        except get_user_model().DoesNotExist:
            return username
        raise forms.ValidationError(self.error_messages['duplicate_username'])

class CustomUserAdmin(UserAdmin):
    form = CustomUserChangeForm
    add_form = CustomUserCreationForm
    fieldsets = (
        (None, {'fields': [('username', 'password'),]}),
        (('Personal info'), {'fields': ('first_name', 'last_name', 'email')}),
        (('Permissions'), {'fields': ('is_active', 'is_staff', 'is_superuser',
                                   'groups', 'user_permissions')}),
        (('Important dates'), {'fields': ('last_login', 'date_joined')}),
        )

admin.site.register(CustomUser, CustomUserAdmin)

Apart from that there is this added to seetings.py

AUTH_USER_MODEL = '<app_name>.CustomUser'

Everything that I found so far suggests that the above given code should make this work, but it doesn't. I spent like 4-5 hours already and I still can't get my head around it. Someone please help

Upvotes: 1

Views: 458

Answers (1)

monte
monte

Reputation: 555

Create your User model like so:

from django.core import validators
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.models import UserManager

class User(AbstractBaseUser, PermissionsMixin):

    username = models.CharField(_('username'), max_length=75, unique=True,
        help_text=_('Required. 30 characters or fewer. Letters, numbers and '
                    'underscores characters'),
        validators=[
            validators.RegexValidator(re.compile('^[\w]+$'), 
            _('Enter a valid username.'), 'invalid')
        ])
    first_name = models.CharField(_('first name'), max_length=254, blank=True)
    last_name = models.CharField(_('last name'), max_length=30, blank=True)
    email = models.EmailField(_('email address'), max_length = 254, unique = True, null = True)
    is_staff = models.BooleanField(_('staff status'), default=False,
        help_text=_('Designates whether the user can log into this admin '
                    'site.'))
    is_active = models.BooleanField(_('active'), default=True,
        help_text=_('Designates whether this user should be treated as '
                    'active. Unselect this instead of deleting accounts.'))
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)

    objects = UserManager()

    USERNAME_FIELD = 'username'
    REQUIRED_FIELDS = ['first_name']

    def get_full_name(self):
        return self.name

    def get_short_name(self):
        return self.username

Don't forget to add your custom fields!

Use a custom admin like so:

@admin.register(models.User)
class CustomUserAdmin(UserAdmin):
    list_display = ('name', 'username', 'is_staff', )
    list_filter = ('is_staff', )
    search_fields = ('first_name', 'last_name', 'username', )
    readonly_fields = ('date_joined', 'last_login', )
    fieldsets = (
        (None, {
            'fields': ('username', 'password')
        }),
        ("Personal Information", {
            'fields': ('first_name', 'last_name', 'email')
        }),
        ("Permissions", {
            'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')
        }),
        ("Important Dates", {
            'fields': ('last_login', 'date_joined')
        }),
    )

Then finally add it to your settings:

AUTH_USER_MODEL = '<app_name>.User'

A working demonstration can be found in my GitHub repository.

Upvotes: 1

Related Questions