原文作者:我辈李想
版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。
DRF应用和管理
【DRF配置管理】Django安装DRF框架并生成openapi风格文档
【DRF配置管理】如何实现JWT身份验证
【DRF配置管理】如何使用序列化:验证码、注册和登录
【DRF配置管理】如何结合ORM实现排序、模糊搜索、范围查询
【DRF配置管理】如何在视图类使用get_objects()
【DRF配置管理】如何实现RBAC页面菜单和按钮权限
【DRF配置管理】如何建立coreapi风格api接口文档
【DRF配置管理】如何建立swagger风格api接口文档
一、常见用法
class Roles(models.Model):
"""角色表"""
role_name = models.CharField(verbose_name='角色名称', max_length=32)
permissions = models.ManyToManyField(verbose_name='拥有的所有权限', to='Permissions')
creat_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
alter_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
class Meta:
verbose_name = '权限组'
verbose_name_plural = '权限组'
app_label = 'users'
def __str__(self):
return self.role_name
class Permissions(models.Model):
"""权限"""
method_choices = ((u'POST', u'增'), (u'DELETE', u'删'), (u'PUT', u'改'), (u'PATCH', u'局部改'), (u'GET', u'查'))
name = models.CharField(max_length=30, verbose_name='权限名:')
sign = models.CharField(max_length=30, unique=True, verbose_name='权限标识')
menu = models.BooleanField(verbose_name='是否为菜单') # True为菜单,False为接口
method = models.CharField(max_length=8, blank=True, default='', choices=method_choices, verbose_name='方法')
path = models.CharField(max_length=200, blank=True, default='', verbose_name='请求路径正则')
desc = models.CharField(max_length=30, blank=True, default='', verbose_name='权限描述')
weight = models.IntegerField(verbose_name='排序权重', default=0)
pid = models.ForeignKey('self', null=True, blank=True, on_delete=models.CASCADE, verbose_name='父权限')
creat_time = models.DateTimeField(verbose_name='创建时间', auto_now_add=True)
alter_time = models.DateTimeField(verbose_name='修改时间', auto_now=True)
objects = models.Manager()
class Meta:
verbose_name = '权限'
verbose_name_plural = verbose_name
ordering = ['id']
app_label = 'users'
def __str__(self):
if self.pid:
return '二级菜单:' + self.name
else:
return '一级菜单:' + self.name
二、实时计算边界
class UserSerializer(ModelSerializer):
permissions = serializers.SerializerMethodField()
class Meta:
model = LoginUser
fields = ['uuid', 'username', 'phone', 'user_permissions', 'permissions']
def get_permissions(self, obj):
permissions = obj.roles.order_by('-permissions__pid__weight', '-permissions__weight').values(
'permissions__id',
'permissions__menu',
'permissions__name',
'permissions__path',
'permissions__weight', # 权重
'permissions__pid__id', # 一级菜单
'permissions__pid__menu', # 一级菜单
'permissions__pid__name', # 一级菜单
'permissions__pid__path', # 一级菜单
'permissions__pid__weight', # 一级菜单权重
).distinct()
permission_list = [] # 全部权限
permission_menu_dict = {} # 菜单权限
for permission in permissions:
# 获取一级菜单并把二级菜单作为children
if permission.get('permissions__pid__menu'):
if permission_menu_dict.get(str(permission.get('permissions__pid__id'))):
permission_menu_dict[str(permission.get('permissions__pid__id'))]['children'].append({
'name': permission.get('permissions__name'),
'path': permission.get('permissions__path'),
'weight': permission.get('permissions__weight')
})
else:
permission_menu_dict[str(permission.get('permissions__pid__id'))] = {
'name': permission.get('permissions__pid__name'),
'path': permission.get('permissions__pid__path'),
'weight': permission.get('permissions__pid__weight'),
'children': [{
'name': permission.get('permissions__name'),
'path': permission.get('permissions__path'),
'weight': permission.get('permissions__weight')
}]
}
elif permission.get('permissions__menu') and not permission_menu_dict.get(
str(permission.get('permissions__id'))):
permission_menu_dict[str(permission.get('permissions__id'))] = {
'name': permission.get('permissions__name'),
'path': permission.get('permissions__path'),
'weight': permission.get('permissions__weight'),
'children': []
}
permission_list.append(permission.get('permissions__path'))
return {
'permissions': permissions,
'permission_menu': permission_menu_dict,
'permission_list': permission_list
}