9

I'm learning Django and need some help.

I need to include an extra boolean field in my User Model (auth_user table in the db I believe) and have it be displayed in the admin interface when managing users, like the staff status field in this image...

127:0.0.1:8000/admin/user :

enter image description here

and...

127.0.0.1:8000/admin/auth/user/2/change/ :

enter image description here

I'm unsure on how to approach this. I understand I'll have to extend the AbstractUser model and then perhaps manually add the field into the db, but then how do I update the new field for the view, form and templates for the admin interface? Will I have to rewrite the django admin source code for all of these or is there an simpler way?

1

5 Answers 5

11

This is how I did it:

Note: This should be done when you are creating a new project.

Adding field(s) to User model :-

models.py:

from django.db import models
from django.contrib.auth.models import AbstractUser

class User(AbstractUser):
   gender = models.BooleanField(default=True) # True for male and False for female
   # you can add more fields here.

Overriding the default User model :-

settings.py:

# the example_app is an app in which models.py is defined
AUTH_USER_MODEL = 'example_app.User' 

Displaying the model on admin page :-

admin.py:

from django.contrib import admin
from .models import User

admin.site.register(User)
Sign up to request clarification or add additional context in comments.

1 Comment

I am getting error Manager is not available
10

The best way is to create new Model with User OneToOneField. e.g

class UserProfile(models.Model):
   user = models.OneToOneField(User)
   phone = models.CharField(max_length=256, blank=True, null=True)
   gender = models.CharField(
        max_length=1, choices=(('m', _('Male')), ('f', _('Female'))),
        blank=True, null=True)

You can play with django admin either in User Model or UserProfile Model and can display the fields in Admin accordingly

1 Comment

How these fields can be displayed after migration?
4

You have two options, they are:

  1. Extend the existing User model by adding another model and linking it to the User model using one-to-one relation. See here.

  2. Write your own user model and use it, which would be difficult for a newbie. See here.

Comments

2

July, 2023 Update:

You can extend User model with OneToOneField() to add extra fields. *You can also see my answer explaining how to set up email and password authentication with AbstractUser or AbstractBaseUser and PermissionsMixin.

First, run the command below to create account app:

python manage.py startapp account

Then, set account app to INSTALLED_APPS in settings.py as shown below:

# "settings.py"

INSTALLED_APPS = [
    ...
    "account", # Here
]

Then, create UserProfile model in account/models.py as shown below. *user field extends User model with OneToOneField():

# "account/models.py"

from django.db import models
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import User

class UserProfile(models.Model):
    user = models.OneToOneField(
        User, 
        verbose_name=_("user"), 
        on_delete=models.CASCADE
    )
    age = models.PositiveSmallIntegerField(_("age"))
    gender = models.CharField(_("gender"), max_length=20)
    married = models.BooleanField(_("married"))

Then, create UserProfileInline and UserAdmin classes in account/admin.py as shown below. *With admin.site.unregister(User), unregistering User model registered by default is necessary otherwise there is error:

# "account/admin.py"

from django.contrib import admin
from .models import UserProfile
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import User

admin.site.unregister(User) # Necessary

class UserProfileInline(admin.TabularInline):
    model = UserProfile

@admin.register(User)
class UserAdmin(BaseUserAdmin):
    inlines = (UserProfileInline,)

Then, run the command below:

python manage.py makemigrations && python manage.py migrate

Then, run the command below:

python manage.py runserver 0.0.0.0:8000

Finally, you could extend User model with extra fields as shown below:

enter image description here

Comments

0
#managers.py  Create new file.
from django.contrib.auth.base_user import BaseUserManager
from django.utils.translation import ugettext_lazy as _
class CustomUserManager(BaseUserManager):
    def create_user(self, email, password, **extra_fields):
        if not email:
            raise ValueError(_('The Email must be set'))
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save()
        return user
    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault('is_staff', True)
        extra_fields.setdefault('is_superuser', True)
        extra_fields.setdefault('is_active', True)

        if extra_fields.get('is_staff') is not True:
            raise ValueError(_('Superuser must have is_staff=True.'))
        if extra_fields.get('is_superuser') is not True:
            raise ValueError(_('Superuser must have is_superuser=True.'))
        return self.create_user(email, password, **extra_fields)

#models.py  Create your models here.
from django.db import models
from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.utils.translation import gettext_lazy as _
from .managers import CustomUserManager
class User(AbstractBaseUser,PermissionsMixin):
    first_name =models.CharField(max_length=250)
    email = models.EmailField(_('email address'), unique=True)
    mobile =models.CharField(max_length=10)
    status = models.BooleanField(default=True)
    is_active = models.BooleanField(default=True)
    is_staff = models.BooleanField(default=False)
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []
    object =CustomUserManager()
    # add more your fields
    
#admin.py
from django.contrib import admin
from .models import User
@admin.register(User)
class UserAdmin(admin.ModelAdmin):
    list_display = ('email','mobile','password')
#setting.py
AUTH_USER_MODEL = 'users.User'

# run command
python manage.py makemigrations
python manage.py migrate

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.