Django-guardian: 使用“assign_perm”时如何优化查询?

创建于 2020-08-20  ·  2评论  ·  资料来源: django-guardian/django-guardian

我目前正在做一个项目,其中一个房间有自己的组权限。

当有人创建新房间时,系统将执行以下操作:

  1. 创建房间
  2. 创建具有唯一名称的所有者和员工组,例如Room Owner#room#{pk}
  3. 从 Room 类获取所有者和员工权限列表
  4. 给每个小组分配一个任务
  5. 为用户分配所有者组权限

这是我的房间模型:

class Room(models.Model):
    # ...fields

    PERMISSION_GROUPS = [
        'owner': [
            ('view_room', _('...')),
            ('change_room', _('...')),
            ('delete_room', _('...')),

            ('open_room', _('...')),
            ('close_room', _('...'))
        ],
        'staff': [
            ('view_room', _('...')),
            ('open_room', _('...')),
            ('close_room', _('...'))    
        ]
    ]

这是我创建房间和生成组权限的代码:

from guardian.shortcuts import assign_perm

class CreateRoomView(generics.CreateAPIView):
    def _get_permission_string(self, perm):
        """
        Get string permission, the return is like 'room.add_room'
        """
        return f'room.{perm.codename}'

    def post(self):
        # Create a room
        body = {}
        room = Room.objects.create(**body)

        # Get content type
        ctype = ContentType.objects.get_for_model(Room)

        # Define name of owner and staff group for this room permission
        owner_group_name = _('Room Owner#room#{pk}')
        staff_group_name = _('Room Staff#room#{pk}')

        # Create group
        owner_group = Group.objects.create(
            name=owner_group_name.format(pk=room.pk))
        staff_group = Group.objects.create(
            name=staff_group_name.format(pk=room.pk))

        # Get permissions by group permissions
        owner_perms = Permission.objects.filter(
            codename__in=Room.PERMISSION_GROUPS.get('owner'), content_type=ctype)
        staff_perms = Permission.objects.filter(
            codename__in=Room.PERMISSION_GROUPS.get('staff'), content_type=ctype)

        # Assign owner permissions to the group
        for owner_perm in owner_perms:
            perm = self._get_permission_string(owner_perm)
            assign_perm(perm, owner_group, obj=room)

        # Assign staff permissions to the group
        for staff_perm in staff_perms:
            perm = self._get_permission_string(staff_perm)
            assign_perm(perm, staff_group, obj=room)

        # Assign owner group permission to the user
        request.user.groups.add(owner_group)

当我查看查询日志时,在此过程中执行了很多查询。

其实还有几个组和上面的赋值过程,不过我只是举了几个例子,所以不会太多。如果计算的话,这个过程中运行的查询执行可能会

那么,如何针对这个问题优化查询呢? 任何人都可以分享如何做得更好。

谢谢,

最有用的评论

  1. 使用直接外键,参见https://django-guardian.readthedocs.io/en/stable/userguide/performance.html#direct -foreign-keys

  2. 您可以将Permission实例传递给assign_permperm = self._get_permission_string(owner_perm)导致每个权限的额外查询。

  3. 如果这还不够,您可以批量分配权限,请参阅下面的代码。 但请注意,我没有测试此代码。 它可能需要调整,它可能根本不起作用。


前:

# Assign owner permissions to the group
for owner_perm in owner_perms:
    perm = self._get_permission_string(owner_perm)
    assign_perm(perm, owner_group, obj=room)

# Assign staff permissions to the group
for staff_perm in staff_perms:
    perm = self._get_permission_string(staff_perm)
    assign_perm(perm, staff_group, obj=room)

后:

# RoomGroupObjectPermission is the model from suggestion 1, use direct foreign keys
room_group_object_permissions = [
    RoomGroupObjectPermission(
        permission=owner_perm, group=owner_group, content_object=room,
    )
    for owner_perm in owner_perms
] + [
    RoomGroupObjectPermission(
        permission=staff_perm, group=staff_group, content_object=room,
    )
    for staff_perm in staff_perms
]

RoomGroupObjectPermission.objects.bulk_create(room_group_object_permissions)

所有2条评论

  1. 使用直接外键,参见https://django-guardian.readthedocs.io/en/stable/userguide/performance.html#direct -foreign-keys

  2. 您可以将Permission实例传递给assign_permperm = self._get_permission_string(owner_perm)导致每个权限的额外查询。

  3. 如果这还不够,您可以批量分配权限,请参阅下面的代码。 但请注意,我没有测试此代码。 它可能需要调整,它可能根本不起作用。


前:

# Assign owner permissions to the group
for owner_perm in owner_perms:
    perm = self._get_permission_string(owner_perm)
    assign_perm(perm, owner_group, obj=room)

# Assign staff permissions to the group
for staff_perm in staff_perms:
    perm = self._get_permission_string(staff_perm)
    assign_perm(perm, staff_group, obj=room)

后:

# RoomGroupObjectPermission is the model from suggestion 1, use direct foreign keys
room_group_object_permissions = [
    RoomGroupObjectPermission(
        permission=owner_perm, group=owner_group, content_object=room,
    )
    for owner_perm in owner_perms
] + [
    RoomGroupObjectPermission(
        permission=staff_perm, group=staff_group, content_object=room,
    )
    for staff_perm in staff_perms
]

RoomGroupObjectPermission.objects.bulk_create(room_group_object_permissions)

我的天啊。 我错过了这个。 我决定使用第一个。 谢谢,

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

johnthagen picture johnthagen  ·  9评论

Allan-Nava picture Allan-Nava  ·  35评论

lukaszb picture lukaszb  ·  14评论

g-as picture g-as  ·  10评论

Dzejkob picture Dzejkob  ·  28评论