from typing import List from django.core.cache import cache from loguru import logger from users.models import User, Menu # 替换为你的实际 app 名 def get_user_permissions(user_id: int) -> List[str]: """ 获取用户所有按钮级权限标识(permission_code) 利用 Django ORM 的多对多关系链式查询 """ cache_key = f"user_permissions_{user_id}" permissions = cache.get(cache_key) logger.info(f"当前缓存的权限列表:{permissions}") if permissions is None: try: # 链式查询:用户 → 角色 → 菜单(仅按钮类型) permissions = list( Menu.objects.filter( roles__users__id=user_id, # 通过 roles__users 反向关联到用户 menu_type=2, # 2 = 按钮 status=True ) .values_list('permission_code', flat=True) .distinct() ) logger.info(f"当前获取到的权限列表:{permissions}") cache.set(cache_key, permissions, 3600) # 缓存1小时 except User.DoesNotExist: return [] logger.info(f"当前用户的权限列表:{permissions}") return permissions def has_permission(user_id: int, permission_code: str) -> bool: """检查用户是否拥有指定权限""" if not permission_code: return True return permission_code in get_user_permissions(user_id) def clear_user_permissions_cache(user_id: int): """清除用户权限缓存(当角色或菜单变更时调用)""" cache.delete(f"user_permissions_{user_id}") # 批量清除缓存的辅助函数(可选) def clear_all_users_permissions_cache(): """清除所有用户权限缓存(谨慎使用)""" # 实际项目中可通过信号或更精细的方式处理 cache.clear() # 或遍历已知用户ID def build_menu_tree(menus): """高效构建菜单树(O(n) 时间复杂度)""" # 1. 将菜单列表转为字典,key=id menu_dict = {} for menu in menus: menu_dict[menu.id] = { 'id': menu.id, 'name': menu.name, 'code': menu.code, 'path': menu.path, 'component': menu.component, 'icon': menu.icon, 'order_num': menu.order_num, 'parent_id': menu.parent_id, # ✅ 只存 ID,避免对象引用 'permission_code': menu.permission_code, 'menu_type': menu.menu_type, 'children': [] # 初始化为空列表 } # 2. 构建树结构 tree = [] for menu_id, node in menu_dict.items(): parent_id = node['parent_id'] if parent_id is None or parent_id not in menu_dict: # 根节点(parent_id 为 None 或指向不存在的父节点) tree.append(node) else: # 添加到父节点的 children menu_dict[parent_id]['children'].append(node) # 3. (可选)按 order_num 排序 def sort_children(nodes): nodes.sort(key=lambda x: x['order_num'] or 0) for node in nodes: sort_children(node['children']) sort_children(tree) return tree