You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django自定义用户模型中忽略is_active字段?

Fix "This account is inactive" Error with Custom Django User Model Using Status Field

I'm trying to create a custom user model in Django, replacing multiple boolean fields (like is_active, is_staff, is_superuser) with a single status integer field to manage user permissions. Here's my model code:

from django.db import models
from django.contrib.auth.models import AbstractUser
from django.utils.translation import ugettext_lazy as _

class MyUser(AbstractUser):
    username = None
    is_staff = None
    is_superuser = None
    is_active = None
    email = models.EmailField(_('email address'), unique=True)
    status = models.PositiveSmallIntegerField(default=0)

I also added this to settings.py:

AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.AllowAllUsersModelBackend']

But when trying to log in, I get the error: "This account is inactive". How can I ignore the is_active field in my custom user model?

Let's break down the problem and fix it step by step:

1. Why the Error Happens

Your approach of setting is_active = None in the model doesn't actually remove the is_active field from the database. AbstractUser inherits this field from AbstractBaseUser, and assigning None doesn't properly exclude it. Even with AllowAllUsersModelBackend, Django's authentication flow still checks for the is_active attribute—and if the field exists in the database with a False value (the default might not be what you expect here), you'll get that error.

2. Proper Fix 1: Use AbstractBaseUser for Full Control

For a fully custom user model that replaces the default boolean permission fields, it's better to inherit from AbstractBaseUser (instead of AbstractUser), as it gives you complete control over which fields are included.

Step 1: Create a Custom User Manager

First, define a manager to handle user creation:

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.utils.translation import ugettext_lazy as _

class MyUserManager(BaseUserManager):
    def create_user(self, email, password=None, **extra_fields):
        if not email:
            raise ValueError(_('The Email field must be set'))
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password=None, **extra_fields):
        # Use your status field to define superuser permissions (e.g., status=2)
        extra_fields.setdefault('status', 2)
        return self.create_user(email, password, **extra_fields)

Step 2: Define the Custom User Model

Now build your model without the default boolean fields, using status instead:

class MyUser(AbstractBaseUser):
    email = models.EmailField(_('email address'), unique=True)
    status = models.PositiveSmallIntegerField(default=0, help_text="0: Inactive, 1: Regular User, 2: Admin/Superuser")
    
    objects = MyUserManager()

    # Set email as the unique identifier for authentication
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    # Implement permission checks using the status field
    def has_perm(self, perm, obj=None):
        # Allow regular users (status >=1) to have basic permissions
        return self.status >= 1

    def has_module_perms(self, app_label):
        return self.status >= 1

    # Map status to is_staff for admin access (optional but useful)
    @property
    def is_staff(self):
        # Let status=2 users access the Django admin
        return self.status >= 2

Step 3: Update Settings

Add these to settings.py:

# Point Django to your custom user model
AUTH_USER_MODEL = 'your_app_name.MyUser'

# Use the default backend (we've handled permissions via our model methods)
AUTHENTICATION_BACKENDS = ['django.contrib.auth.backends.ModelBackend']

3. Proper Fix 2: Custom Authentication Backend (If You Want to Keep AbstractUser)

If you prefer to stick with AbstractUser, you need to create a custom authentication backend that skips the is_active check entirely, and properly exclude the default boolean fields from your model.

Step 1: Fix the Model (Exclude Default Fields)

Instead of setting fields to None, use Meta.exclude to remove them:

class MyUser(AbstractUser):
    username = None
    email = models.EmailField(_('email address'), unique=True)
    status = models.PositiveSmallIntegerField(default=0)

    class Meta:
        exclude = ['is_active', 'is_staff', 'is_superuser']

    # Map status to required attributes for Django's auth system
    @property
    def is_active(self):
        # Define active users via status (e.g., status >=1 is active)
        return self.status >= 1

    @property
    def is_staff(self):
        return self.status >= 2

    @property
    def is_superuser(self):
        return self.status == 2

Step 2: Create a Custom Backend

Create a backends.py file in your app:

from django.contrib.auth.backends import ModelBackend

class SkipActiveCheckBackend(ModelBackend):
    def user_can_authenticate(self, user):
        # Bypass the default is_active check entirely
        return True

Step 3: Update Settings

AUTH_USER_MODEL = 'your_app_name.MyUser'
AUTHENTICATION_BACKENDS = ['your_app_name.backends.SkipActiveCheckBackend']

Final Notes

  • Always run makemigrations and migrate after modifying your user model to apply database changes.
  • If you're starting a new project, using AbstractBaseUser is the cleaner approach for full customization.
  • Make sure your status field values are clearly documented so your team understands what each value represents.

内容的提问来源于stack exchange,提问作者Oto Shavadze

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.30 03:57:28