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

如何在Django Admin中区分多用户类型并注册同一模型的两个管理版本?

解决Django Admin中多用户类型的区分显示问题

这个问题我之前也碰到过——Django Admin不允许同一个模型被重复注册,所以你直接两次调用admin.site.register(User, ...)必然会触发django.contrib.admin.sites.AlreadyRegistered错误。解决这个问题最优雅的方案是使用代理模型(Proxy Model),它不会新增数据库表,只是对原User模型的封装,让Admin识别为两个独立的模型,从而实现分别注册和显示。

步骤1:创建User模型的代理类

在你的models.py中,为Client和Partner分别创建代理模型,设置不同的显示名称:

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

class User(AbstractUser):
    is_partner = models.BooleanField(default=False)
    is_client = models.BooleanField(default=False)
    email = models.EmailField(unique=True)

# 新增Client用户代理模型
class ClientUser(User):
    class Meta:
        proxy = True
        verbose_name = "Client User"
        verbose_name_plural = "Client Users"

# 新增Partner用户代理模型
class PartnerUser(User):
    class Meta:
        proxy = True
        verbose_name = "Partner User"
        verbose_name_plural = "Partner Users"

# 你的原有Profile模型保持不变
class ClientProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # 你的其他字段...

class PartnerProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE)
    # 你的其他字段...

步骤2:调整Admin类并注册代理模型

修改你的admin.py,让原有的Admin类对应代理模型,然后分别注册:

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import ClientUser, PartnerUser, ClientProfile, PartnerProfile

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

class ClientUserAdmin(UserAdmin):
    inlines = (ClientProfileInline, )
    
    # 只筛选is_client=True的用户
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.filter(is_client=True)
    
    def get_inline_instances(self, request, obj=None):
        if not obj:
            return list()
        return super(ClientUserAdmin, self).get_inline_instances(request, obj)

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

class PartnerUserAdmin(UserAdmin):
    inlines = (PartnerProfileInline, )
    
    # 只筛选is_partner=True的用户
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        return qs.filter(is_partner=True)
    
    def get_inline_instances(self, request, obj=None):
        if not obj:
            return list()
        return super(PartnerUserAdmin, self).get_inline_instances(request, obj)

# 注册代理模型而非原User模型
admin.site.register(ClientUser, ClientUserAdmin)
admin.site.register(PartnerUser, PartnerUserAdmin)

为什么这个方案可行?

  • 代理模型本质上还是操作原User数据表,不会增加数据库负担;
  • Django允许为不同的代理模型注册独立的Admin类,避免了重复注册的错误;
  • 你可以通过verbose_name自定义Admin首页的显示名称,实现清晰的区分;
  • 原有的get_queryset过滤逻辑和Inline配置完全可以复用,不需要大幅修改代码。

如果之后需要保留原User模型的全局Admin入口,只需额外注册一次原User模型即可:

from .models import User
admin.site.register(User, UserAdmin)

内容的提问来源于stack exchange,提问作者adrian oviedo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:03:41