Django QuerySet:将查询结果格式化为自定义词典

问题描述 投票:0回答:2

我正在为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中做到这一点。

django django-queryset
2个回答
0
投票

您也许可以使用列表理解来达到预期的结果。

# 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]

0
投票

我已经找到了我想要的解决方案... 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'
          ]
        }
      ]
    }
  ]
}

在我的用户界面中:enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.