pythondjangomodel-view-controllerdjango-models

Custom user model in django


I want to create a custom user model using django.contrib.auth.models.AbstractUser as stated in the djangodocs:

If you’re entirely happy with Django’s User model and you just want to add some additional profile information, you can simply subclass django.contrib.auth.models.AbstractUser and add your custom profile fields. This class provides the full implementation of the default User as an abstract model.

So I inherited the AbstractUser class in my Users class and added a field. But when I run the python manage.py syncdb I get the following error:

CommandError: One or more models did not validate:
admin.logentry: 'user' has a relation with model login.users, which has either 
not been installed or is abstract.

I went through other questions on stackoverflow but couldn't resolve the error. Here is my code:

models.py

from django.conf import settings
from django.db import models
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.models import AbstractUser
from django.contrib import admin

class Users(AbstractUser):
    college = models.CharField(max_length=40)

admin.site.register(Users, UserAdmin)

admin.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from django.contrib.auth.forms import UserChangeForm, UserCreationForm
from login.models import Users
from django import forms

class UsersChangeForm(UserChangeForm):
    class Meta(UserChangeForm.Meta):
        model = Users

class UsersAdmin(UserAdmin):
    form = UsersChangeForm

    fieldsets = UserAdmin.fieldsets + (
            (None, {'fields': ('college',)}),
    )


admin.site.register(Users, UsersAdmin)

settings.py

INSTALLED_APPS = (
    'forms',
    'login',
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
)

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

AUTH_USER_MODEL = 'login.users'

EDIT:

I want to store the user information in the same table as auth_user and not in a new table.


Solution

  • I did this in one of my project. I was surprised to see that you extended User because the doc says something else :) You can extend Django User model, but if you only want to add new fields (not change its behavior), you should use a OneToOneField.

    If you wish to store information related to User, you can use a one-to-one
    relationship to a model containing the fields for additional information.
    

    So, as you can see in the link, your code should look like:

    from django.contrib.auth.models import User
    
    class MyUser(models.Model):
        user = models.OneToOneField(User)
    
        # Or a ForeingKey to the College table?
        college = models.CharField(max_length=40)
    
        other_data = ...