Django User Model

Model

  • Single, definitive source of info about data
  • Python class that subclasses django.db.models.Model.

Importance of Django User Model

  • Django User Model objects are the core of the authentication system
  • In order to make the most of the auth system, it is necessary to understand the default Django User Model as well as the ways to customize it
  • The auth system handles
  • user accounts
  • groups
  • permissions
  • sessions

User accounts

  • User Model objects represent the users of the site
  • Only one class of user exists in Django’s authentication framework
  • superusers or staff are simply attributes of user objects
  • User objects have two many-to-many fields: groups and user_permissions

Groups

  • Generic way of categorizing users
  • to apply permissions, or some other label, to those users
  • A user can belong to any number of groups
  • A user in a group automatically has the permissions granted to that group

Permissions

  • Created when manage.py migrate is run
  • When django.contrib.auth is listed in project’s INSTALLED_APPS setting, four default permissions – add, change, delete, and view – are created for each Django model defined in installed applications
  • Cached on the user object by ModelBackend after the first time they need to be fetched for a permissions check
    def user_gains_perms(request, user_id):
        user = get_object_or_404(User, pk=user_id)
    # any permission check will cache the current set of permissions
        user.has_perm(‘myapp.change_blogpost’)
  • Can be assigned to specific users and groups of users
  • Can be set per type of object and also per specific object instance

Sessions

  • Used to hook the authentication system into request objects
  • Provides a request.user attribute on every request to represent the current user
    if request.user.is_authenticated:
        # Do something for authenticated users.
        …

Customizing Django User Model

There are three ways to customize the User Model

  • Proxy Model
  • OneToOneField
  • Custom User Model

Proxy Model

  • Simple Django models that happen to have a one-to-one link with a user model
  • Allows for any of the features offered by proxy models including default ordering, custom managers, or custom model methods.
  • No changes are made in the database
  • Additional methods can be added
  • Only Python behaviour of the Model is changed
    # models.py
    
    class Author(User):
    …
        class Meta:
            proxy = True

OneToOneField

  • Stores information in the database in a new table
  • Also called a profile model, as it can store non-auth related information
  • Custom Fields can be added
from django.contrib.auth.models import User


class Employee(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    extra_field = …

Custom User Model

  • Allows maximum customization compared to the other two ways
  • Implementation
  • subclass Abstract Base User to create a new Model
    • provides basic user implementation and password handling
  • in project settings.py, set AUTH_USER_MODEL = ‘
    • some compulsory methods have to be added to custom User model
    • is_staff()
    • is_active()
    • has_perm(perm, obj=None)
    • has_module_perms(app_label)
  • normal Python import by referencing the relative path will work to register this model in admins.py
  • also, an alternative import can be used to register this model
    • from django.contrib.auth import get_user_model
    • admin.site.register(get_user_model())
  • Additional customization options
  • set up User Manager
    • subclass BaseUserManager
    • implement two methods to go through the additional custom requirements when creating a new user via django commands
    • create_user
    • create_superuser
  • set up Admin Forms
# models.py

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

class UserManager(BaseUserManager):
def create_user(self, email, password=None, is_active=True, is_staff=None, is_admin=False):
if not email:
raise ValueError(‘Users must have an email address’)
if not password:
raise ValueError(‘Users must have a password’)
user_obj = self.model(email = self.normalize_email(email))
user_obj.set_password(password)
user_obj.staff = is_staff
user_obj.admin = is_admin
user_obj.active = is_active
user_obj.save(using=self._db)
return user_obj

/* optional method */
def create_staffuser(self, email, password=None):
    user_obj = self.create_user(email, password=password, is_staff=True)
    return user_obj

def create_superuser(self, email, password=None):
    user_obj = self.create_user(email, password=password, is_staff=True, is_admin=True)
    return user_obj
class User(AbstractBaseUser):
email = models.EmailField(max_length=255, unique=True)
timestamp = models.DateTimeField(auto_now_add=True)

USERNAME_FIELD = 'email'

objects = UserManager()
/ these methods are needed by Django Admin /
def is_staff(self):
return True

def is_active(self):
    return True

def has_perm(self, perm, obj=None):
    return True

def has_module_perms(self, app_label):
    return True