mirror of https://github.com/jumpserver/jumpserver
perf: 优化标签搜索资产使用的关系
parent
f0ffa2408d
commit
18707d365b
|
@ -3,6 +3,7 @@
|
||||||
import base64
|
import base64
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
|
from collections import defaultdict
|
||||||
|
|
||||||
from django.core.cache import cache
|
from django.core.cache import cache
|
||||||
from django.core.exceptions import ImproperlyConfigured
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
|
@ -180,7 +181,7 @@ class LabelFilterBackend(filters.BaseFilterBackend):
|
||||||
]
|
]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_label_ids(labels_id):
|
def parse_labels(labels_id):
|
||||||
from labels.models import Label
|
from labels.models import Label
|
||||||
label_ids = [i.strip() for i in labels_id.split(',')]
|
label_ids = [i.strip() for i in labels_id.split(',')]
|
||||||
cleaned = []
|
cleaned = []
|
||||||
|
@ -201,8 +202,8 @@ class LabelFilterBackend(filters.BaseFilterBackend):
|
||||||
q = Q()
|
q = Q()
|
||||||
for kwarg in args:
|
for kwarg in args:
|
||||||
q |= Q(**kwarg)
|
q |= Q(**kwarg)
|
||||||
ids = Label.objects.filter(q).values_list('id', flat=True)
|
labels = Label.objects.filter(q)
|
||||||
cleaned.extend(list(ids))
|
cleaned.extend(list(labels))
|
||||||
return cleaned
|
return cleaned
|
||||||
|
|
||||||
def filter_queryset(self, request, queryset, view):
|
def filter_queryset(self, request, queryset, view):
|
||||||
|
@ -221,13 +222,23 @@ class LabelFilterBackend(filters.BaseFilterBackend):
|
||||||
app_label = model._meta.app_label
|
app_label = model._meta.app_label
|
||||||
model_name = model._meta.model_name
|
model_name = model._meta.model_name
|
||||||
|
|
||||||
resources = labeled_resource_cls.objects.filter(
|
full_resources = labeled_resource_cls.objects.filter(
|
||||||
res_type__app_label=app_label, res_type__model=model_name,
|
res_type__app_label=app_label, res_type__model=model_name,
|
||||||
)
|
)
|
||||||
label_ids = self.parse_label_ids(labels_id)
|
labels = self.parse_labels(labels_id)
|
||||||
resources = model.filter_resources_by_labels(resources, label_ids)
|
grouped = defaultdict(set)
|
||||||
|
for label in labels:
|
||||||
|
grouped[label.name].add(label.id)
|
||||||
|
|
||||||
|
matched_ids = set()
|
||||||
|
for name, label_ids in grouped.items():
|
||||||
|
resources = model.filter_resources_by_labels(full_resources, label_ids, rel='any')
|
||||||
res_ids = resources.values_list('res_id', flat=True)
|
res_ids = resources.values_list('res_id', flat=True)
|
||||||
queryset = queryset.filter(id__in=set(res_ids))
|
if not matched_ids:
|
||||||
|
matched_ids = set(res_ids)
|
||||||
|
else:
|
||||||
|
matched_ids &= set(res_ids)
|
||||||
|
queryset = queryset.filter(id__in=matched_ids)
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from django.contrib.contenttypes.fields import GenericRelation
|
from django.contrib.contenttypes.fields import GenericRelation
|
||||||
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.db.models import OneToOneField, Count
|
from django.db.models import OneToOneField, Count
|
||||||
|
|
||||||
|
@ -38,8 +39,11 @@ class LabeledMixin(models.Model):
|
||||||
self.real.labels.set(value, bulk=False)
|
self.real.labels.set(value, bulk=False)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def filter_resources_by_labels(cls, resources, label_ids):
|
def filter_resources_by_labels(cls, resources, label_ids, rel='all'):
|
||||||
|
if rel == 'all':
|
||||||
return cls._get_filter_res_by_labels_m2m_all(resources, label_ids)
|
return cls._get_filter_res_by_labels_m2m_all(resources, label_ids)
|
||||||
|
else:
|
||||||
|
return cls._get_filter_res_by_labels_m2m_in(resources, label_ids)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _get_filter_res_by_labels_m2m_in(cls, resources, label_ids):
|
def _get_filter_res_by_labels_m2m_in(cls, resources, label_ids):
|
||||||
|
@ -60,7 +64,8 @@ class LabeledMixin(models.Model):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_labels_filter_attr_q(cls, value, match):
|
def get_labels_filter_attr_q(cls, value, match):
|
||||||
resources = LabeledResource.objects.all()
|
res_type = ContentType.objects.get_for_model(cls.label_model())
|
||||||
|
resources = LabeledResource.objects.all().filter(res_type=res_type)
|
||||||
if not value:
|
if not value:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue