我正在为Django-React应用开发RBAC系统。我具有要生成的特定对象结构,但是我不确定如何直接从Django的QuerySet API中执行此操作。
当前,我有这个查询
permissions |= PermissionAssignment.objects.filter(role=role['role__id']).values(
'permission__object__id',
'permission__object__name',
'permission__operation__id',
'permission__operation__name'
)
这将在我的前端返回此对象:
permissions: [
{
permission__object__id: 1,
permission__object__name: 'Post',
permission__operation__id: 1,
permission__operation__name: 'Read'
},
{
permission__object__id: 1,
permission__object__name: 'Post',
permission__operation__id: 2,
permission__operation__name: 'Write'
},
{
permission__object__id: 2,
permission__object__name: 'Event',
permission__operation__id: 2,
permission__operation__name: 'Read'
},
]
我不需要权限对象具有这种复杂的结构。我只需要掌握对象名称和当前用户对此对象启用的操作。因此,基本上,我只需要将其结构化为:
permissions:[
"Post": {
operations: ['Read', 'Write']
},
"Event": {
operations: ['Read']
}
]
我知道我可以在前端上处理原始结果以获取所需的内容,但是当我可以立即在服务器端级别上格式化结果时,我认为这不是必需的,只是我不确定如何在Django中做到这一点。
您也许可以使用列表理解来达到预期的结果。
# NOTE: we use prefetch_related to avoid extra queries every time we access the object
permissions_qs = PermissionAssignment.objects.filter(role=role['role__id']).prefetch_related('object', 'operation')
d = {}
[d.update({p.object.name: {'operations': [p.operation.name]}}) if p.object.name not in d else d[p.object.name]['operations'].append(p.operations.name) for p in permissions_qs]
我已经找到了我想要的解决方案... JSON响应的结构与我在上面的问题中定义的结构不同,但我想它要好得多。
但是,我在这里发布代码是因为我对自己的方法有第二个想法,即我开始认为查询非常昂贵...也许有人可以帮助检查它总体上是否不错,或者确实是一个不好的做法。
代码:
roles = RoleAssignment.objects.none()
modules = RoleModule.objects.none()
module_objects = ModuleObject.objects.none()
objects = Object.objects.none()
permissions = PermissionAssignment.objects.none()
roles = RoleAssignment.objects.filter(user=user).values('role__id', 'role__name')
for role in roles:
modules |= RoleModule.objects.filter(role=role['role__id']).values(
'role__id',
'module__id',
'module__name',
'module__slug',
'module__fontawesome_icon'
)
permissions |= PermissionAssignment.objects.filter(role=role['role__id']).values(
'permission__object__id',
'permission__object__name',
'permission__operation__id',
'permission__operation__name'
)
for module in modules:
module_objects |= ModuleObject.objects.filter(module=module['module__id']).values(
'module__id',
'module__name',
'object__id',
'object__name',
'object__slug'
)
# format modules to include respective objects and permissions
# this logic is primarily designed so that sidebar links can be...
# ...generated seamlessly thru frontend
formatted_modules = [
{
"name": x['module__name'],
"slug": x['module__slug'],
"icon": x['module__fontawesome_icon'],
"objects": [
{
"name": y['object__name'],
"slug": y['object__slug'],
"operations": [z['permission__operation__name'] for z in permissions if z['permission__object__id']==y['object__id']]
}
for y in module_objects if x['module__id']==y['module__id']
]
}
for x in modules
]
然后将其作为响应发送:
return Response({
"modules": formatted_modules
})
JSON等效项:
{
modules: [
{
name: 'Web Content',
slug: 'web-content',
icon: 'fas fa-newspaper',
objects: [
{
name: 'Post',
slug: 'post',
operations: [
'Read',
'Write',
'Modify',
'Delete'
]
}
]
},
{
name: 'Bids and Awards',
slug: 'bids-and-awards',
icon: 'fas fa-project-diagram',
objects: [
{
name: 'SRBP Goods & Services',
slug: 'srbp-goods-services',
operations: [
'Read',
'Write',
'Modify',
'Delete'
]
},
{
name: 'SRBP Infrastructure',
slug: 'srbp-infrastructure',
operations: [
'Read',
'Write',
'Modify',
'Delete'
]
}
]
}
]
}