perf: 优化 api sql 查询

This commit is contained in:
ibuler
2023-02-07 16:21:26 +08:00
parent 47c5f18c6e
commit e7202ac984
13 changed files with 150 additions and 104 deletions

View File

@@ -1,12 +1,13 @@
from django.db.models import Count
from django.db.models import Q, Count
from django.utils.translation import ugettext as _
from rest_framework.decorators import action
from rest_framework.exceptions import PermissionDenied
from common.api import JMSModelViewSet
from orgs.utils import current_org
from .permission import PermissionViewSet
from ..filters import RoleFilter
from ..models import Role, SystemRole, OrgRole
from ..models import Role, SystemRole, OrgRole, RoleBinding
from ..serializers import RoleSerializer, RoleUserSerializer
__all__ = [
@@ -33,6 +34,7 @@ class RoleViewSet(JMSModelViewSet):
if instance.builtin:
error = _("Internal role, can't be destroy")
raise PermissionDenied(error)
with tmp_to_root_org():
if instance.users.count() >= 1:
error = _("The role has been bound to users, can't be destroy")
@@ -54,6 +56,24 @@ class RoleViewSet(JMSModelViewSet):
return
instance.permissions.set(clone.get_permissions())
@staticmethod
def set_users_amount(queryset):
"""设置角色的用户绑定数量,以减少查询"""
org_id = current_org.id
q = Q(role__scope=Role.Scope.system) | Q(role__scope=Role.Scope.org, org_id=org_id)
role_bindings = RoleBinding.objects.filter(q).values_list('role_id').annotate(user_count=Count('user_id'))
role_user_amount_mapper = {role_id: user_count for role_id, user_count in role_bindings}
queryset = queryset.annotate(permissions_amount=Count('permissions'))
queryset = list(queryset)
for role in queryset:
role.users_amount = role_user_amount_mapper.get(role.id, 0)
return queryset
def filter_queryset(self, queryset):
queryset = super().filter_queryset(queryset)
queryset = self.set_users_amount(queryset)
return queryset
def perform_update(self, serializer):
instance = serializer.instance
if instance.builtin:
@@ -61,10 +81,6 @@ class RoleViewSet(JMSModelViewSet):
raise PermissionDenied(error)
return super().perform_update(serializer)
def get_queryset(self):
queryset = super().get_queryset().annotate(permissions_amount=Count('permissions'))
return queryset
@action(methods=['GET'], detail=True)
def users(self, *args, **kwargs):
role = self.get_object()
@@ -73,11 +89,13 @@ class RoleViewSet(JMSModelViewSet):
class SystemRoleViewSet(RoleViewSet):
queryset = SystemRole.objects.all()
def get_queryset(self):
return super().get_queryset().filter(scope='system')
class OrgRoleViewSet(RoleViewSet):
queryset = OrgRole.objects.all()
def get_queryset(self):
return super().get_queryset().filter(scope='org')
class BaseRolePermissionsViewSet(PermissionViewSet):