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

如何在Django中建模并实现账号与账号专属用户功能?

嘿,我之前刚好碰到过完全一样的需求——给Django项目做「账号(Account)」+「账号专属用户」的分层,而且必须要兼容自带的Admin后台,折腾了好一阵才找到顺手的方案,分享给你参考:

核心思路

核心是要保留Django Auth的原生能力(登录、权限、Session这些),同时把Account作为顶层实体,让多个User关联到同一个Account。我试过直接新增Account和AccountUser中间表,但Admin适配确实麻烦,后来调整成「Profile关联」或者「自定义User模型」的方式,就顺畅多了。

方案一:基于原生User的Profile关联(适合已启动的项目)

如果你的项目已经用了原生的auth.User,不想替换它,就用这种方式:

1. 定义Account主模型

先建一个代表「账号」的模型,这是所有用户的顶层归属:

from django.db import models

class Account(models.Model):
    name = models.CharField(max_length=100, unique=True, verbose_name="账号名称")
    created_at = models.DateTimeField(auto_now_add=True, verbose_name="创建时间")
    # 可以根据需求加其他字段,比如账号类型、过期时间、企业信息等

    def __str__(self):
        return self.name

2. 用Profile关联User和Account

创建一个和User一对一关联的Profile模型,用来存储用户和账号的绑定关系,还能加账号内的角色:

from django.contrib.auth.models import User

class AccountUserProfile(models.Model):
    user = models.OneToOneField(User, on_delete=models.CASCADE, related_name="account_profile", verbose_name="关联用户")
    account = models.ForeignKey(Account, on_delete=models.CASCADE, related_name="users", verbose_name="所属账号")
    
    # 可选:账号内的角色区分
    ROLE_CHOICES = (
        ('admin', '账号管理员'),
        ('member', '普通成员'),
    )
    role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='member', verbose_name="账号角色")

    def __str__(self):
        return f"{self.user.username} - {self.account.name} ({self.get_role_display()})"

3. 适配Django Admin(重点解决你的痛点)

要让Admin能同时管理账号、用户,并且在用户页面直接看到账号关联信息,需要自定义Admin类:

from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib import admin
from .models import Account, AccountUserProfile

# 给User页面加账号关联的Inline
class AccountUserProfileInline(admin.StackedInline):
    model = AccountUserProfile
    can_delete = False
    verbose_name_plural = "账号关联信息"

# 替换原生的UserAdmin
class CustomUserAdmin(BaseUserAdmin):
    inlines = (AccountUserProfileInline,)
    # 可选:在用户列表页直接显示所属账号
    list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff', 'get_account_name')

    def get_account_name(self, obj):
        if hasattr(obj, 'account_profile'):
            return obj.account_profile.account.name
        return "未关联账号"
    get_account_name.short_description = "所属账号"

admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)

# 给Account页面加下属用户的Inline
class AccountUserInline(admin.TabularInline):
    model = AccountUserProfile
    fk_name = 'account'
    verbose_name_plural = "账号成员"

class AccountAdmin(admin.ModelAdmin):
    inlines = (AccountUserInline,)
    list_display = ('name', 'created_at', 'get_member_count')

    def get_member_count(self, obj):
        return obj.users.count()
    get_member_count.short_description = "成员数量"

admin.site.register(Account, AccountAdmin)

这样配置后,你在Admin里:

  • 打开用户详情页,能直接设置/查看所属账号和角色
  • 打开账号详情页,能看到所有关联的用户,还能直接添加新用户
  • 用户列表页和账号列表页都有直观的统计信息

方案二:自定义User模型(适合新项目)

如果你的项目还在初期,强烈推荐直接自定义User模型,这样不用额外的Profile表,结构更简洁:

1. 先定义Account模型(和方案一一样)

2. 自定义User模型

from django.contrib.auth.models import AbstractUser

class CustomUser(AbstractUser):
    account = models.ForeignKey(Account, on_delete=models.SET_NULL, null=True, blank=True, related_name="users", verbose_name="所属账号")
    # 可选:账号内角色
    ROLE_CHOICES = (
        ('admin', '账号管理员'),
        ('member', '普通成员'),
    )
    account_role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='member', verbose_name="账号角色")

然后在settings.py里指定自定义User:

AUTH_USER_MODEL = 'your_app_name.CustomUser'

3. 适配Admin

这种方式的Admin适配更简单,直接继承UserAdmin并添加字段即可:

from django.contrib.auth.admin import UserAdmin
from django.contrib import admin
from .models import Account, CustomUser

class CustomUserAdmin(UserAdmin):
    # 在用户列表页显示账号信息
    list_display = ('username', 'email', 'account', 'account_role', 'is_staff')
    # 在编辑页面添加账号相关字段
    fieldsets = UserAdmin.fieldsets + (
        ('账号关联信息', {'fields': ('account', 'account_role')}),
    )
    add_fieldsets = UserAdmin.add_fieldsets + (
        ('账号关联信息', {'fields': ('account', 'account_role')}),
    )

admin.site.register(CustomUser, CustomUserAdmin)

# Account的Admin配置和方案一类似,加用户Inline即可
class AccountUserInline(admin.TabularInline):
    model = CustomUser
    fk_name = 'account'
    verbose_name_plural = "账号成员"

class AccountAdmin(admin.ModelAdmin):
    inlines = (AccountUserInline,)
    list_display = ('name', 'created_at', 'get_member_count')

    def get_member_count(self, obj):
        return obj.users.count()
    get_member_count.short_description = "成员数量"

admin.site.register(Account, AccountAdmin)
额外优化(可选)

如果需要做权限控制,比如普通管理员只能查看/编辑自己账号下的用户,可以在Admin的get_queryset方法里限制:

class CustomUserAdmin(UserAdmin):
    # ... 其他代码
    def get_queryset(self, request):
        qs = super().get_queryset(request)
        if not request.user.is_superuser:
            return qs.filter(account=request.user.account)
        return qs

这个方案我在好几个生产项目里都用过,既保留了Django Auth的所有原生功能,又完美实现了「账号-用户」的分层,Admin的体验也和原生一致,应该能解决你的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:48:27