Django 管理:从自定义用户模型中删除记录

问题描述

我创建了一个自定义用户模型 (users_user),用于注册新用户(创建新的自定义用户记录)和登录。但是如果我转到管理页面,并尝试删除用户记录从那里,它似乎试图从用户模型 (auth_user) 中删除记录。我收到错误

IntegrityError at /admin/users/user/
insert or update on table "django_admin_log" violates foreign key constraint "django_admin_log_user_id_c564eba6_fk_auth_user_id"
DETAIL:  Key (user_id)=(3) is not present in table "auth_user".

有没有办法可以保留标准的 Django 管理页面(下面的屏幕截图),但引用我的自定义用户模型而不是标准的 auth_user 模型?

users/models.py

from django.db import models
from PIL import Image
from django.conf import settings
from django.contrib.auth.models import (
    BaseUserManager,AbstractBaseUser
)

#~~~ CUSTOM USER ~~~

class UserManager(BaseUserManager):
    def create_user(self,email,username,password=None):
        print('username in UserManager.create_user(): ' + username)

        if not email:
            raise ValueError('Users must have an email address')

        if not username:
            raise ValueError('Users must have a username')

        user = self.model(
            email=self.normalize_email(email),username=username,#todo: confirm,is this right?
        )

        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_staffuser(self,password):
        """
        Creates and saves a staff user with the given email and password.
        """
        user = self.create_user(
            email,password=password,)
        user.staff = True
        user.save(using=self._db)
        return user

    def create_superuser(self,password):
        print('username in UserManager.create_superuser(): ' + username)
        """
        Creates and saves a superuser with the given email and password.
        """
        user = self.create_user(
            email,)
        user.staff = True
        user.admin = True
        user.save(using=self._db)
        return user




class User(AbstractBaseUser):
    email = models.EmailField(
        verbose_name='email address',max_length=255,unique=True,)
    username = models.CharField(max_length=100,unique=True)
    is_active = models.BooleanField(default=True)
    staff = models.BooleanField(default=False) # a admin user; non super-user
    admin = models.BooleanField(default=False) # a superuser

    # notice the absence of a "Password field",that is built in.

    USERNAME_FIELD = 'username'
    required_FIELDS = ['email'] # Email & Password are required by default.

    objects = UserManager()


    def get_short_username(self):
        # The user is identified by their email address
        return self.username[0:10] # Get first 10 chars of username

    def __str__(self):
        return self.username

    def has_perm(self,perm,obj=None):
        "Does the user have a specific permission?"
        # Simplest possible answer: Yes,always
        return True

    def has_module_perms(self,app_label):
        "Does the user have permissions to view the app `app_label`?"
        # Simplest possible answer: Yes,always
        return True

    @property
    def is_staff(self):
        "Is the user a member of staff?"
        return self.staff

    @property
    def is_admin(self):
        "Is the user a admin member?"
        return self.admin






class Profile(models.Model):
    user = models.OnetoOneField(User,on_delete=models.CASCADE)
    image = models.ImageField(default='default.jpg',upload_to='profile_pics')

    def __str__(self):
        return f'{self.user.username} Profile'

    # def save(self,*args,**kwargs):
    #     super().save(*args,**kwargs)

    #     img = Image.open(self.image.path)

    #     if img.height > 300 or img.width > 300:
    #         output_size = (300,300)
    #         img.thumbnail(output_size)
    #         img.save(self.image.path)

users/admin.py:

from django.contrib import admin
from .models import Profile

from django.contrib.auth import get_user_model
User = get_user_model()

admin.site.register(Profile)
admin.site.register(User) #<- THIS IS REGISTERING THE WRONG USER MODEL

enter image description here

解决方法

我正在处理的 django 应用程序中有一个类似的抽象用户模型。这就是我设置 admin.py 的方式,它可以根据您的要求工作。

我已将您的 admin.py 修改为更像我的。我相信当您使用“get_user_model”函数时,它会导致问题。

此外,除非您有特殊原因需要添加电子邮件、用户名、is_active、员工等字段。对抽象用户模型进行子类化已经提供了所有默认字段。我已经添加了一个额外的字段来将用户的外键添加到配置文件类型模型中。我使用 UserAdmin 模型和字段集在 django 管理员中显示我的自定义用户字段。

from django.contrib import admin

# Import your abstract user model from the apps models.py
from .models import Profile,User

# Import the auth UserAdmin model
from django.contrib.auth.admin import UserAdmin


# I use this to add the custom fields the django admin form,you may not need it. 
fields = list(UserAdmin.fieldsets)
fields[0] = (None,{'fields': ('username','password','account')})
UserAdmin.fieldsets = tuple(fields)

admin.site.register(Profile)
# Register the two models
admin.site.register(User,UserAdmin) 

作为参考,这是我的models.py 对于用户模型的样子。

class User(AbstractUser):
account = models.ForeignKey('Account',on_delete=models.PROTECT,null=True,blank=True,unique=True)

class Meta:
    permissions = (
                   ("make_admin","Can view and edit most admin features."),("edit_permissions","Admin user can modify user permissions."),("edit_nacha","User can edit and modify NACHA files."),("edit_commissions","User can override commisions."),("view_reports","User can view admin reports."),)
,

您需要更新您的 settings.py 并指向自定义用户模型

settings.py

# Custom User model
AUTH_USER_MODEL = 'my_app.User'

admin.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from my_app.models import User

admin.site.register(User,UserAdmin)

见:https://docs.djangoproject.com/en/3.2/topics/auth/customizing/#substituting-a-custom-user-model