Actualmente estoy trabajando en un proyecto en el que una habitación tiene sus propios permisos de grupo.
Cuando alguien crea una nueva habitación, el sistema hará lo siguiente:
Room Owner#room#{pk}
Aquí está mi modelo de habitación:
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', _('...'))
]
]
Este es mi código para crear sala y generar permisos de grupo:
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)
Cuando miro los registros de consultas, se están realizando muchas consultas en este proceso.
En realidad, todavía hay algunos grupos y el proceso de asignación como el anterior, pero solo incluí algunos ejemplos, por lo que no hay demasiados.Si se calcula, puede haber más de 50 ejecuciones de consultas que se ejecutan en este proceso.
Entonces, ¿cómo puedo optimizar la consulta para este problema? ¿Alguien puede compartir cómo hacerlo mejor?
Gracias,
Use claves externas directas, consulte https://django-guardian.readthedocs.io/en/stable/userguide/performance.html#direct -foreign-keys
Puede pasar instancias de Permission
a assign_perm
. perm = self._get_permission_string(owner_perm)
conduce a una consulta adicional por permiso.
Si esto no es suficiente, puede asignar los permisos de forma masiva, consulte el código a continuación. Pero tenga en cuenta que no probé este código. Puede que necesite ajustes, puede que no funcione en absoluto.
Antes:
# 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)
Después:
# 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)
Dios mío. Echaba de menos este. Decidí usar el primero. Gracias,
Comentario más útil
Use claves externas directas, consulte https://django-guardian.readthedocs.io/en/stable/userguide/performance.html#direct -foreign-keys
Puede pasar instancias de
Permission
aassign_perm
.perm = self._get_permission_string(owner_perm)
conduce a una consulta adicional por permiso.Si esto no es suficiente, puede asignar los permisos de forma masiva, consulte el código a continuación. Pero tenga en cuenta que no probé este código. Puede que necesite ajustes, puede que no funcione en absoluto.
Antes:
Después: