Ich arbeite gerade an einem Projekt, bei dem ein Raum seine eigenen Gruppenberechtigungen hat.
Wenn jemand einen neuen Raum erstellt, geht das System wie folgt vor:
Room Owner#room#{pk}
Hier ist mein Room-Modell:
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', _('...'))
]
]
Dies ist mein Code zum Erstellen von Räumen und Generieren von Gruppenberechtigungen:
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)
Wenn ich mir die Abfrageprotokolle ansehe, werden in diesem Prozess viele Abfragen ausgeführt.
Tatsächlich gibt es noch ein paar Gruppen und den Zuweisungsprozess wie oben, aber ich habe nur einige Beispiele aufgenommen, damit es nicht zu viele sind. Wenn berechnet, können in diesem Prozess mehr als 50 Abfrageausführungen ausgeführt werden.
Wie kann ich die Abfrage für dieses Problem optimieren? Kann jemand sagen, wie man es besser macht.
Dankeschön,
Direkte Fremdschlüssel verwenden, siehe https://django-guardian.readthedocs.io/en/stable/userguide/performance.html#direct -foreign-keys
Sie können Instanzen von Permission
an assign_perm
. perm = self._get_permission_string(owner_perm)
führt zu einer zusätzlichen Abfrage pro Berechtigung.
Wenn dies nicht ausreicht, können Sie die Berechtigungen massenweise zuweisen, siehe Code unten. Aber seien Sie sich bewusst, dass ich diesen Code nicht getestet habe. Möglicherweise müssen Anpassungen vorgenommen werden, es funktioniert möglicherweise überhaupt nicht.
Vor:
# 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)
Nach:
# 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)
OMG. Ich habe diesen verpasst. Ich habe mich für den ersten entschieden. Dankeschön,
Hilfreichster Kommentar
Direkte Fremdschlüssel verwenden, siehe https://django-guardian.readthedocs.io/en/stable/userguide/performance.html#direct -foreign-keys
Sie können Instanzen von
Permission
anassign_perm
.perm = self._get_permission_string(owner_perm)
führt zu einer zusätzlichen Abfrage pro Berechtigung.Wenn dies nicht ausreicht, können Sie die Berechtigungen massenweise zuweisen, siehe Code unten. Aber seien Sie sich bewusst, dass ich diesen Code nicht getestet habe. Möglicherweise müssen Anpassungen vorgenommen werden, es funktioniert möglicherweise überhaupt nicht.
Vor:
Nach: