django remove unwanted user fields in models using AbstractUser

Viewed 663

I'm a beginner in django and I'm working on user authentication. I'm using Abstractuser and default User model to create the users. However, there a lot of unnecessary information being gathered that is of no use to my project.

This is my models.py:

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

class User(AbstractUser):
    pass

These are the fields that are generated:

('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('email', models.EmailField(blank=True, max_length=254, verbose_name='email address')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions')),

The only fields I would like to be present in my project are: password, username, first_name, last_name, email & date_joined.

I've searched and only found ways to delete username and appoint email as the default.

How can I customize the user model to have the fields that are of use in my project? Any help is appreciated.

Edit: I didn't say anything about making the authentication through email. I wanna keep using the username as default just deleting the unnecessary fields.

2 Answers

There is another abstraction that allows what you want and it's AbstractBaseUser and it's all explained there:

The easiest way to construct a compliant custom user model is to inherit from AbstractBaseUser. AbstractBaseUser provides the core implementation of a user model, including hashed passwords and tokenized password resets. You must then provide some key implementation details

So AbstractUser also uses AbstractBaseUser as a start and then adds things.

Note that if you don't add the PermissionsMixin (which adds groups and permissions fields), the admin becomes unusable as will several other packages that tie into Django's default authorization framework.

However, if that is of no concern to you, you are free to only implement the fields you want.

Basics

So you basically want to authenticate based on Email field and don't want the permissions. You have to inherit from AbstractBaseUser which doesn't include permissions fields. To make EmailField the primary authentication field you have to define a variable USERNAME_FIELD in your user model to set the field to be used in place of username.

DJANGO ADMIN

get_short_name and get_full_name are used by Django admin to get the name of user. For your use case I have created a model.

Code:

from django.utils.translation import gettext_lazy as _
from django.contrib.auth.validators import UnicodeUsernameValidator
from django.contrib.auth.models import AbstractBaseUser

class User(AbstractBaseUser):
    username_validator = UnicodeUsernameValidator()

    username = models.CharField(max_length=150,unique=True,validators=[username_validator],error_messages={'unique': _("A user with that username already exists."),},)
    first_name = models.CharField(_('first name'), max_length=30, blank=True)
    last_name = models.CharField(_('last name'), max_length=150, blank=True)
    email = models.EmailField(_('email address'), blank=True)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    last_update = models.DateTimeField(_('last updated'), auto_now=True)
    date_joined = models.DateTimeField(_('date joined'), default=timezone.now)


    class Meta:
        ordering = ['username']

    def __str__(self):
        return self.email
Related