update. 完善用户相关基础数据的模型与接口配置
This commit is contained in:
+147
-24
@@ -1,17 +1,109 @@
|
||||
from django.contrib import admin
|
||||
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
|
||||
from django.utils.html import format_html
|
||||
from import_export.admin import ImportExportModelAdmin
|
||||
|
||||
from .models import Department, Role, Menu
|
||||
from .models import User
|
||||
from .models import Department
|
||||
from .models import Role, Permission
|
||||
|
||||
|
||||
# ========== 菜单管理 ==========
|
||||
@admin.register(Menu)
|
||||
class MenuAdmin(admin.ModelAdmin):
|
||||
list_display = (
|
||||
'name', 'code', 'menu_type_display', 'path', 'permission_code', 'parent_link', 'order_num', 'status')
|
||||
list_filter = ('menu_type', 'status', 'parent')
|
||||
search_fields = ('name', 'code', 'permission_code')
|
||||
ordering = ('order_num', 'id')
|
||||
list_editable = ('order_num', 'status') # 允许在列表页直接编辑
|
||||
list_per_page = 20
|
||||
|
||||
# 自定义字段:显示菜单类型
|
||||
def menu_type_display(self, obj):
|
||||
types = {0: '目录', 1: '菜单', 2: '按钮'}
|
||||
return types.get(obj.menu_type, '未知')
|
||||
|
||||
menu_type_display.short_description = '类型'
|
||||
|
||||
# 自定义字段:父菜单链接(可点击)
|
||||
def parent_link(self, obj):
|
||||
if obj.parent:
|
||||
url = f"/admin/users/menu/{obj.parent.id}/change/"
|
||||
return format_html('<a href="{}">{}</a>', url, obj.parent.name)
|
||||
return '-'
|
||||
|
||||
parent_link.short_description = '父菜单'
|
||||
|
||||
|
||||
# ========== 角色管理 ==========
|
||||
class RoleMenuInline(admin.TabularInline):
|
||||
"""
|
||||
内联管理:在角色编辑页直接分配菜单
|
||||
"""
|
||||
model = Role.menus.through # 使用自动创建的中间表
|
||||
verbose_name = "菜单权限"
|
||||
verbose_name_plural = "菜单权限"
|
||||
extra = 1 # 默认显示1个空行
|
||||
|
||||
# 优化显示:只显示关键字段
|
||||
def formfield_for_foreignkey(self, db_field, request, **kwargs):
|
||||
if db_field.name == "menu":
|
||||
# 可以在这里过滤菜单选项,例如只显示状态为True的
|
||||
kwargs["queryset"] = Menu.objects.filter(status=True)
|
||||
return super().formfield_for_foreignkey(db_field, request, **kwargs)
|
||||
|
||||
|
||||
@admin.register(Role)
|
||||
class RoleAdmin(admin.ModelAdmin):
|
||||
list_display = ('name', 'code', 'description', 'user_count', 'menu_count', 'status', 'created_at')
|
||||
list_filter = ('status', 'created_at')
|
||||
search_fields = ('name', 'code', 'description')
|
||||
ordering = ('-created_at',)
|
||||
list_per_page = 20
|
||||
|
||||
# 使用内联管理菜单权限
|
||||
inlines = [RoleMenuInline]
|
||||
|
||||
# 排除 menus 字段,因为已经在内联中处理
|
||||
exclude = ('menus',)
|
||||
|
||||
# 自定义字段:关联用户数量
|
||||
def user_count(self, obj):
|
||||
count = obj.users.count()
|
||||
if count:
|
||||
url = f"/admin/users/user/?roles__id__exact={obj.id}"
|
||||
return format_html('<a href="{}">{}</a>', url, count)
|
||||
return 0
|
||||
|
||||
user_count.short_description = '用户数'
|
||||
|
||||
# 自定义字段:关联菜单数量
|
||||
def menu_count(self, obj):
|
||||
count = obj.menus.count()
|
||||
if count:
|
||||
url = f"/admin/users/menu/?roles__id__exact={obj.id}"
|
||||
return format_html('<a href="{}">{}</a>', url, count)
|
||||
return 0
|
||||
|
||||
menu_count.short_description = '菜单数'
|
||||
|
||||
|
||||
# ========== 用户管理 ==========
|
||||
class UserRoleInline(admin.TabularInline):
|
||||
"""
|
||||
内联管理:在用户编辑页直接分配角色
|
||||
"""
|
||||
model = User.roles.through
|
||||
verbose_name = "角色"
|
||||
verbose_name_plural = "角色"
|
||||
extra = 1
|
||||
|
||||
|
||||
@admin.register(User)
|
||||
class UserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
||||
list_display = ('username', 'cname', 'dept', 'is_active', 'is_staff')
|
||||
list_display = ('username', 'cname', 'dept', 'phone', 'is_active', 'is_staff')
|
||||
list_filter = ('is_active', 'is_staff', 'dept')
|
||||
search_fields = ('username', 'cname')
|
||||
search_fields = ('username', 'cname', 'phone',)
|
||||
fieldsets = (
|
||||
(None, {'fields': ('username', 'password')}),
|
||||
('个人信息', {'fields': ('cname', 'dept')}),
|
||||
@@ -24,33 +116,64 @@ class UserAdmin(BaseUserAdmin, ImportExportModelAdmin):
|
||||
'fields': ('username', 'cname', 'password1', 'password2', 'dept'),
|
||||
}),
|
||||
)
|
||||
ordering = ('username',)
|
||||
ordering = ('username', '-date_joined',)
|
||||
filter_horizontal = ('groups', 'user_permissions', 'roles') # 如果 roles 是 ManyToMany
|
||||
list_per_page = 20
|
||||
# 使用内联管理角色
|
||||
inlines = [UserRoleInline]
|
||||
|
||||
# 排除 roles 字段,因为已经在内联中处理
|
||||
exclude = ('roles',)
|
||||
|
||||
# 自定义字段:显示所有角色名称
|
||||
def role_names(self, obj):
|
||||
roles = obj.roles.all()
|
||||
if roles:
|
||||
names = ', '.join([role.name for role in roles])
|
||||
return names[:50] + '...' if len(names) > 50 else names
|
||||
return '-'
|
||||
|
||||
role_names.short_description = '角色'
|
||||
|
||||
|
||||
# ========== 部门管理 ==========
|
||||
@admin.register(Department)
|
||||
class DepartmentAdmin(ImportExportModelAdmin):
|
||||
list_display = ('name', 'parent', 'order')
|
||||
list_filter = ('parent',)
|
||||
search_fields = ('name',)
|
||||
ordering = ('order', 'name')
|
||||
class DepartmentAdmin(admin.ModelAdmin):
|
||||
list_display = ('name_with_indent', 'parent_link', 'order', 'user_count')
|
||||
list_editable = ('order',)
|
||||
ordering = ('order', 'id')
|
||||
list_per_page = 30
|
||||
|
||||
def get_queryset(self, request):
|
||||
# 优化查询,避免 N+1
|
||||
return super().get_queryset(request).select_related('parent')
|
||||
|
||||
@admin.register(Role)
|
||||
class RoleAdmin(ImportExportModelAdmin):
|
||||
list_display = ('name', 'permission_count')
|
||||
search_fields = ('name',)
|
||||
filter_horizontal = ('permissions',)
|
||||
def name_with_indent(self, obj):
|
||||
"""根据层级缩进显示部门名称"""
|
||||
level = 0
|
||||
current = obj.parent
|
||||
while current:
|
||||
level += 1
|
||||
current = current.parent
|
||||
indent = "=>" * level
|
||||
return format_html('{}{}', indent, obj.name)
|
||||
|
||||
def permission_count(self, obj):
|
||||
return obj.permissions.count()
|
||||
name_with_indent.short_description = "部门名称"
|
||||
name_with_indent.allow_tags = True
|
||||
|
||||
permission_count.short_description = "权限数量"
|
||||
def parent_link(self, obj):
|
||||
if obj.parent:
|
||||
url = f"/admin/users/department/{obj.parent.id}/change/"
|
||||
return format_html('<a href="{}">{}</a>', url, obj.parent.name)
|
||||
return '-'
|
||||
|
||||
parent_link.short_description = "上级部门"
|
||||
|
||||
@admin.register(Permission)
|
||||
class PermissionAdmin(ImportExportModelAdmin):
|
||||
list_display = ('resource', 'action', 'desc')
|
||||
list_filter = ('resource', 'action')
|
||||
search_fields = ('resource', 'desc')
|
||||
ordering = ('resource', 'action')
|
||||
def user_count(self, obj):
|
||||
count = obj.user_set.count()
|
||||
if count:
|
||||
url = f"/admin/users/user/?department__id__exact={obj.id}"
|
||||
return format_html('<a href="{}">{}</a>', url, count)
|
||||
return 0
|
||||
|
||||
user_count.short_description = "用户数"
|
||||
|
||||
Reference in New Issue
Block a user