Django-guardian: `assign_perm`を使用するときにクエリを最適化するにはどうすればよいですか?

作成日 2020年08月20日  ·  2コメント  ·  ソース: django-guardian/django-guardian

私は現在、1つの部屋に独自のグループ権限があるプロジェクトに取り組んでいます。

誰かが新しい部屋を作成すると、システムは次のことを行います。

  1. 部屋を作成する
  2. Room Owner#room#{pk}などの一意の名前で所有者とスタッフのグループを作成します
  3. ルームクラスから所有者とスタッフの権限のリストを取得します
  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. あなたはのインスタンス渡すことができますPermissionassign_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. あなたはのインスタンス渡すことができますPermissionassign_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 評価