简体   繁体   中英

Extending django User Model (Unable to add extra fields)

I am new to django, I am trying to extend Django User Model with few extra parameters. I tried the following solution and tried different workarounds too but didnt't get successful. Any help would be greatly appreciated.

Here is the code files.

admin -> init__.py

from django.contrib import admin

from django.contrib.auth.admin import UserAdmin

from usermanagement.models import UserProfile 

scrumboard_models = [models.Board, models.Setting, models.CheckList, models.CheckListItem,
                     models.Comments, models.Subscribers, models.Lists,
                     models.Label, models.Card, models.Attachment, models.Team]

admin.site.register(scrumboard_models)

class UserProfileAdmin(UserAdmin):

    list_display = (
        'id', 'first_name', 'username', 'email', 'is_active', 'dob'
    )

admin.site.register(UserProfile, UserProfileAdmin)

Settings.py """ Django settings for app project.

Generated by 'django-admin startproject' using Django 3.1.7.

For more information on this file, see

https://docs.djangoproject.com/en/3.1/topics/settings/

For the full list of settings and their values, see

https://docs.djangoproject.com/en/3.1/ref/settings/

"""
import os

from pathlib import Path

# Build paths inside the project like this: BASE_DIR / 'subdir'.

BASE_DIR = Path(__file__).resolve().parent.parent

import datetime

JWT_AUTH = {
  'JWT_ALLOW_REFRESH': True,
    'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=3600),
}

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/3.1/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'v!t5abxm^t@tyj=z5gp!*_%qy=$q-d6g!4zx(!r3_nn)7h^ee7'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = ['*']

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django.contrib.postgres',
    'scrumboard',
    'admin_app',
    'whitenoise.runserver_nostatic',
    'corsheaders',
    'usermanagement',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    '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',
    'whitenoise.middleware.WhiteNoiseMiddleware',
    'corsheaders.middleware.CorsMiddleware',
]

ROOT_URLCONF = 'app.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'app.wsgi.application'

REST_FRAMEWORK = {
    'DEFAULT_FILTER_BACKENDS': [
        'django_filters.rest_framework.DjangoFilterBackend'
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'rest_framework_simplejwt.authentication.JWTAuthentication',
    ],
}

# Database

# https://docs.djangoproject.com/en/3.1/ref/settings/#databases
EMAIL_BACKEND = 'django.core.mail.backends.smtp.EmailBackend'

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        "NAME": os.environ.get('DB_NAME', 'scrumboard'),
        "USER": os.environ.get('USER', 'postgres'),
        "PASSWORD": os.environ.get('PASSWORD', '112233'),
        "HOST": os.environ.get('HOST', 'localhost'),
        "PORT": os.environ.get('DB_PORT', 5432),
    }
}

# Password validation
# https://docs.djangoproject.com/en/3.1/ref/settings/#auth-password-validators

EMAIL_HOST = 'smtp.gmail.com'

EMAIL_USE_TLS = True

EMAIL_PORT = 587

EMAIL_HOST_USER = 'abc@gmail.com'

EMAIL_HOST_PASSWORD = '1234567890'

EMAIL_USE_SSL=False

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/3.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True

# Static files (CSS, JavaScript, Images)

# https://docs.djangoproject.com/en/3.1/howto/static-files/

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage'
MEDIA_URL = '/media/'
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
# ======================================================================================================================
# CORS SETTINGS
# ======================================================================================================================

CORS_ORIGIN_ALLOW_ALL = True

CORS_ALLOW_CREDENTIALS = True

AUTH_USER_MODEL = 'usermanagement.UserProfile'

usermanagement.models.py

from django.db import models

from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager

from django.utils import timezone

from django.utils.translation import gettext_lazy as _

# Create your models here.

class CustomAccountManager(BaseUserManager):

    def create_superuser(self, email, username, first_name, password, **other_fields):

        other_fields.setdefault('is_staff', True)

        other_fields.setdefault('is_superuser', True)

        other_fields.setdefault('is_active', True)

        if other_fields.get('dob') is not True:

            dob = None

        if other_fields.get('is_staff') is not True:

            raise ValueError(
                'Superuser must be assigned to is_staff=True.')
        if other_fields.get('is_superuser') is not True:
            raise ValueError(
                'Superuser must be assigned to is_superuser=True.')
        return self.create_user(email, username, first_name, password, **other_fields)

    def create_user(self, email, username, first_name, password, **other_fields):

        if not email:
            raise ValueError(_('You must provide an email address'))

        email = self.normalize_email(email)

        user = self.model(email=email, username=username,
                          first_name=first_name, password=password, **other_fields)

        user.set_password(password)

        user.save(using=self._db)

        return user

class UserProfile(AbstractBaseUser, PermissionsMixin):

    email = models.EmailField(_('email address'), unique=True)

    username = models.CharField(max_length=150, unique=True)

    first_name = models.CharField(max_length=150, blank=True)

    last_name = models.CharField(max_length=150, blank=True)

    date_joined = models.DateTimeField(default=timezone.now)

    about = models.TextField(_(
        'about'), max_length=500, blank=True)

    is_staff = models.BooleanField(default=False)

    is_active = models.BooleanField(default=False)

    phone_number = models.CharField(max_length=20)

    dob = models.DateField(blank=True, null=True)

    gender = models.CharField(max_length=15)

    objects = CustomAccountManager()

    USERNAME_FIELD = 'email'

    class Meta:

        abstract = False

    def __str__(self):

        return self.username

[Project Structure][1]


  [1]: https://i.stack.imgur.com/06Wkp.png

Parameters dob, gender are added into database but are not showing up in django admin portal.

when I did this kind of thing I had to do the following:

admin.site.unregister(User)
admin.site.register(User, UserProfileAdmin)

Separately I also had this code in my admin.py file:

class ProfileInline(admin.StackedInline):
    model = Profile
    can_delete = False
    verbose_name_plural = 'Profile'
    fk_name = 'user'

class UserProfileAdmin(UserAdmin):
    inlines = (ProfileInline, )

    def get_inline_instances(self, request, obj=None):
        if not obj:
            return list()
        return super(UserProfileAdmin, self).get_inline_instances(request, obj)

My Profile model is just a normal model IE class Profile(models.Model):... Specifically:

class Profile(models.Model):
   user = models.OneToOneField(User, on_delete=models.CASCADE, blank=True)
   otherfield = ...
   dob = ...
   gender = ...
   phone_number = models.CharField(max_length=17, null=True, blank=True)
 ....

    @receiver(post_save, sender=User)
    def create_user_profile(sender, instance, created, **kwargs):
        if created:
            Profile.objects.create(user=instance)

    @receiver(post_save, sender=User)
    def save_user_profile(sender, instance, **kwargs):
        instance.profile.save()
  

I think the base User model may be still in place and you need to unregister it to put in your custom UserProfileAdmin

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM