perf: 修改 filter_q

pull/10547/head
ibuler 2023-05-25 11:42:39 +08:00
parent cabdc3ad42
commit dcd35310cd
4 changed files with 62 additions and 6 deletions

View File

@ -1,6 +1,9 @@
from rest_framework.decorators import action
from rest_framework.response import Response
from common.drf.filters import BaseFilterSet
from orgs.mixins.api import OrgBulkModelViewSet
from .common import ACLFiltersetMixin
from .. import models, serializers
__all__ = ['CommandFilterACLViewSet', 'CommandGroupViewSet']
@ -13,10 +16,16 @@ class CommandGroupViewSet(OrgBulkModelViewSet):
serializer_class = serializers.CommandGroupSerializer
class CommandACLFilter(ACLFiltersetMixin, BaseFilterSet):
class Meta:
model = models.CommandFilterACL
fields = ['name', 'users', 'assets']
class CommandFilterACLViewSet(OrgBulkModelViewSet):
model = models.CommandFilterACL
filterset_fields = ('name',)
search_fields = filterset_fields
filterset_class = CommandACLFilter
search_fields = ['name']
serializer_class = serializers.CommandFilterACLSerializer
rbac_perms = {
'command_review': 'tickets.add_superticket'

39
apps/acls/api/common.py Normal file
View File

@ -0,0 +1,39 @@
from django_filters import rest_framework as drf_filters
from common.drf.filters import BaseFilterSet
from common.utils import is_uuid
class ACLFiltersetMixin(BaseFilterSet):
users = drf_filters.CharFilter(method='filter_user')
assets = drf_filters.CharFilter(method='filter_asset')
@staticmethod
def filter_user(queryset, name, value):
from users.models import User
if not value:
return queryset
if is_uuid(value):
user = User.objects.filter(id=value).first()
else:
user = User.objects.filter(name=value).first()
if not user:
return queryset.none()
q = queryset.model.users.get_filter_q(user)
return queryset.filter(q).distinct()
@staticmethod
def filter_asset(queryset, name, value):
from assets.models import Asset
if not value:
return queryset
if is_uuid(value):
asset = Asset.objects.filter(id=value).first()
else:
asset = Asset.objects.filter(name=value).first()
if not asset:
return queryset.none()
q = queryset.model.assets.get_filter_q(asset)
return queryset.filter(q).distinct()

View File

@ -1,12 +1,19 @@
from common.drf.filters import BaseFilterSet
from orgs.mixins.api import OrgBulkModelViewSet
from .common import ACLFiltersetMixin
from .. import models, serializers
__all__ = ['LoginAssetACLViewSet']
class CommandACLFilter(ACLFiltersetMixin, BaseFilterSet):
class Meta:
model = models.LoginAssetACL
fields = ['name', 'users', 'assets']
class LoginAssetACLViewSet(OrgBulkModelViewSet):
model = models.LoginAssetACL
filterset_fields = ('name', )
search_fields = filterset_fields
filterset_class = CommandACLFilter
search_fields = ['name']
serializer_class = serializers.LoginAssetACLSerializer

View File

@ -502,7 +502,8 @@ class JSONManyToManyDescriptor:
def get_filter_q(self, instance):
model_cls = self.field.model
field_name = self.field.column
q = Q(users__type='all') | Q(users__type='ids', users__ids__contains=[str(instance.id)])
q = Q(**{f'{field_name}__type': 'all'}) | \
Q(**{f'{field_name}__type': 'ids', f'{field_name}__ids__contains': [str(instance.id)]})
queryset_id_attrs = model_cls.objects \
.filter(**{'{}__type'.format(field_name): 'attrs'}) \
.values_list('id', '{}__attrs'.format(field_name))