From 8a646e5ef7d41395024f4f299c5dd9f77134cd4e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=8C=BF=E5=B0=8F=E5=A4=A9?= <1638245306@qq.com>
Date: Fri, 16 Feb 2024 20:13:20 +0800
Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=8A=9F=E8=83=BD:=20=E6=96=B0?=
=?UTF-8?q?=E5=A2=9E=E5=A4=A7=E6=95=B0=E6=8D=AE=E9=80=89=E6=8B=A9=E7=BB=84?=
=?UTF-8?q?=E4=BB=B6?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
backend/application/settings.py | 3 +-
backend/dvadmin/system/views/role.py | 12 +--
backend/dvadmin/utils/filters.py | 125 ++++++++++++++++------
web/package.json | 2 +-
web/src/components/dvaSelect/index.vue | 141 +++++++++++++++++++++++++
web/src/views/system/demo/index.vue | 83 +++++++++++++--
6 files changed, 318 insertions(+), 48 deletions(-)
create mode 100644 web/src/components/dvaSelect/index.vue
diff --git a/backend/application/settings.py b/backend/application/settings.py
index 70446c1..3428ae4 100644
--- a/backend/application/settings.py
+++ b/backend/application/settings.py
@@ -404,10 +404,11 @@ PLUGINS_URL_PATTERNS = []
# ********** 一键导入插件配置开始 **********
# 例如:
# from dvadmin_upgrade_center.settings import * # 升级中心
-from dvadmin_celery.settings import * # celery 异步任务
+#from dvadmin_celery.settings import * # celery 异步任务
# from dvadmin_third.settings import * # 第三方用户管理
# from dvadmin_ak_sk.settings import * # 秘钥管理管理
# from dvadmin_tenants.settings import * # 租户管理
#from dvadmin_social_auth.settings import *
+#from dvadmin_uniapp.settings import *
# ...
# ********** 一键导入插件配置结束 **********
diff --git a/backend/dvadmin/system/views/role.py b/backend/dvadmin/system/views/role.py
index ccbe6d6..a5b5a6f 100644
--- a/backend/dvadmin/system/views/role.py
+++ b/backend/dvadmin/system/views/role.py
@@ -47,12 +47,12 @@ class RoleCreateUpdateSerializer(CustomModelSerializer):
def validate(self, attrs: dict):
return super().validate(attrs)
- def save(self, **kwargs):
- is_superuser = self.request.user.is_superuser
- if not is_superuser:
- self.validated_data.pop('admin')
- data = super().save(**kwargs)
- return data
+ # def save(self, **kwargs):
+ # is_superuser = self.request.user.is_superuser
+ # if not is_superuser:
+ # self.validated_data.pop('admin')
+ # data = super().save(**kwargs)
+ # return data
class Meta:
model = Role
diff --git a/backend/dvadmin/utils/filters.py b/backend/dvadmin/utils/filters.py
index cb61630..05c0dfb 100644
--- a/backend/dvadmin/utils/filters.py
+++ b/backend/dvadmin/utils/filters.py
@@ -12,14 +12,16 @@ from collections import OrderedDict
from functools import reduce
import six
+from django.db import models
from django.db.models import Q, F
from django.db.models.constants import LOOKUP_SEP
from django_filters import utils, FilterSet
+from django_filters.constants import ALL_FIELDS
from django_filters.filters import CharFilter, DateTimeFromToRangeFilter
from django_filters.rest_framework import DjangoFilterBackend
from django_filters.utils import get_model_field
from rest_framework.filters import BaseFilterBackend
-
+from django_filters.conf import settings
from dvadmin.system.models import Dept, ApiWhiteList, RoleMenuButtonPermission
from dvadmin.utils.models import CoreModel
@@ -203,6 +205,7 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
"$": "iregex",
"~": "icontains",
}
+ filter_fields = "__all__"
def construct_search(self, field_name, lookup_expr=None):
lookup = self.lookup_prefixes.get(field_name[0])
@@ -210,14 +213,16 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
field_name = field_name[1:]
else:
lookup = lookup_expr
- if field_name.endswith(lookup):
- return field_name
- return LOOKUP_SEP.join([field_name, lookup])
+ if lookup:
+ if field_name.endswith(lookup):
+ return field_name
+ return LOOKUP_SEP.join([field_name, lookup])
+ return field_name
def find_filter_lookups(self, orm_lookups, search_term_key):
for lookup in orm_lookups:
# if lookup.find(search_term_key) >= 0:
- new_lookup = lookup.split("__")[0]
+ new_lookup = LOOKUP_SEP.join(lookup.split(LOOKUP_SEP)[:-1]) if len(lookup.split(LOOKUP_SEP)) > 1 else lookup
# 修复条件搜索错误 bug
if new_lookup == search_term_key:
return lookup
@@ -233,18 +238,22 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
# TODO: remove assertion in 2.1
if filterset_class is None and hasattr(view, "filter_class"):
utils.deprecate(
- "`%s.filter_class` attribute should be renamed `filterset_class`."
- % view.__class__.__name__
+ "`%s.filter_class` attribute should be renamed `filterset_class`." % view.__class__.__name__
)
filterset_class = getattr(view, "filter_class", None)
# TODO: remove assertion in 2.1
if filterset_fields is None and hasattr(view, "filter_fields"):
utils.deprecate(
- "`%s.filter_fields` attribute should be renamed `filterset_fields`."
- % view.__class__.__name__
+ "`%s.filter_fields` attribute should be renamed `filterset_fields`." % view.__class__.__name__
)
- filterset_fields = getattr(view, "filter_fields", None)
+ self.filter_fields = getattr(view, "filter_fields", None)
+ if isinstance(self.filter_fields, (list, tuple)):
+ filterset_fields = [
+ field[1:] if field[0] in self.lookup_prefixes.keys() else field for field in self.filter_fields
+ ]
+ else:
+ filterset_fields = self.filter_fields
if filterset_class:
filterset_model = filterset_class._meta.model
@@ -264,6 +273,51 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
MetaBase = getattr(self.filterset_base, "Meta", object)
class AutoFilterSet(self.filterset_base):
+ @classmethod
+ def get_all_model_fields(cls, model):
+ opts = model._meta
+
+ return [
+ f.name
+ for f in sorted(opts.fields + opts.many_to_many)
+ if (f.name == "id")
+ or not isinstance(f, models.AutoField)
+ and not (getattr(f.remote_field, "parent_link", False))
+ ]
+
+ @classmethod
+ def get_fields(cls):
+ """
+ Resolve the 'fields' argument that should be used for generating filters on the
+ filterset. This is 'Meta.fields' sans the fields in 'Meta.exclude'.
+ """
+ model = cls._meta.model
+ fields = cls._meta.fields
+ exclude = cls._meta.exclude
+
+ assert not (fields is None and exclude is None), (
+ "Setting 'Meta.model' without either 'Meta.fields' or 'Meta.exclude' "
+ "has been deprecated since 0.15.0 and is now disallowed. Add an explicit "
+ "'Meta.fields' or 'Meta.exclude' to the %s class." % cls.__name__
+ )
+
+ # Setting exclude with no fields implies all other fields.
+ if exclude is not None and fields is None:
+ fields = ALL_FIELDS
+
+ # Resolve ALL_FIELDS into all fields for the filterset's model.
+ if fields == ALL_FIELDS:
+ fields = cls.get_all_model_fields(model)
+
+ # Remove excluded fields
+ exclude = exclude or []
+ if not isinstance(fields, dict):
+ fields = [(f, [settings.DEFAULT_LOOKUP_EXPR]) for f in fields if f not in exclude]
+ else:
+ fields = [(f, lookups) for f, lookups in fields.items() if f not in exclude]
+
+ return OrderedDict(fields)
+
@classmethod
def get_filters(cls):
"""
@@ -292,9 +346,12 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
if field is None:
undefined.append(field_name)
# 更新默认字符串搜索为模糊搜索
- if isinstance(field, (models.CharField)) and filterset_fields == '__all__' and lookups == [
- 'exact']:
- lookups = ['icontains']
+ if (
+ isinstance(field, (models.CharField))
+ and filterset_fields == "__all__"
+ and lookups == ["exact"]
+ ):
+ lookups = ["icontains"]
for lookup_expr in lookups:
filter_name = cls.get_filter_name(field_name, lookup_expr)
@@ -304,20 +361,15 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
continue
if field is not None:
- filters[filter_name] = cls.filter_for_field(
- field, field_name, lookup_expr
- )
+ filters[filter_name] = cls.filter_for_field(field, field_name, lookup_expr)
# Allow Meta.fields to contain declared filters *only* when a list/tuple
if isinstance(cls._meta.fields, (list, tuple)):
- undefined = [
- f for f in undefined if f not in cls.declared_filters
- ]
+ undefined = [f for f in undefined if f not in cls.declared_filters]
if undefined:
raise TypeError(
- "'Meta.fields' must not contain non-model field names: %s"
- % ", ".join(undefined)
+ "'Meta.fields' must not contain non-model field names: %s" % ", ".join(undefined)
)
# Add in declared filters. This is necessary since we don't enforce adding
@@ -339,22 +391,31 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
return queryset
if filterset.__class__.__name__ == "AutoFilterSet":
queryset = filterset.queryset
- orm_lookups = []
- for search_field in filterset.filters:
- if isinstance(filterset.filters[search_field], CharFilter):
- orm_lookups.append(
- self.construct_search(six.text_type(search_field), filterset.filters[search_field].lookup_expr)
- )
- else:
- orm_lookups.append(search_field)
+ filter_fields = filterset.filters if self.filter_fields == "__all__" else self.filter_fields
+ orm_lookup_dict = dict(
+ zip(
+ [field for field in filter_fields],
+ [filterset.filters[lookup].lookup_expr for lookup in filterset.filters.keys()],
+ )
+ )
+ orm_lookups = [
+ self.construct_search(lookup, lookup_expr) for lookup, lookup_expr in orm_lookup_dict.items()
+ ]
+ # print(orm_lookups)
conditions = []
queries = []
for search_term_key in filterset.data.keys():
orm_lookup = self.find_filter_lookups(orm_lookups, search_term_key)
- if not orm_lookup:
+ if not orm_lookup or filterset.data.get(search_term_key) == '':
continue
- query = Q(**{orm_lookup: filterset.data[search_term_key]})
- queries.append(query)
+ filterset_data_len = len(filterset.data.getlist(search_term_key))
+ if filterset_data_len == 1:
+ query = Q(**{orm_lookup: filterset.data[search_term_key]})
+ queries.append(query)
+ elif filterset_data_len == 2:
+ orm_lookup += '__range'
+ query = Q(**{orm_lookup: filterset.data.getlist(search_term_key)})
+ queries.append(query)
if len(queries) > 0:
conditions.append(reduce(operator.and_, queries))
queryset = queryset.filter(reduce(operator.and_, conditions))
diff --git a/web/package.json b/web/package.json
index 28b837f..d4e4679 100644
--- a/web/package.json
+++ b/web/package.json
@@ -25,7 +25,7 @@
"echarts": "^5.4.1",
"echarts-gl": "^2.0.9",
"echarts-wordcloud": "^2.1.0",
- "element-plus": "^2.3.9",
+ "element-plus": "^2.5.5",
"element-tree-line": "^0.2.1",
"font-awesome": "^4.7.0",
"js-cookie": "^3.0.1",
diff --git a/web/src/components/dvaSelect/index.vue b/web/src/components/dvaSelect/index.vue
new file mode 100644
index 0000000..8d58fbe
--- /dev/null
+++ b/web/src/components/dvaSelect/index.vue
@@ -0,0 +1,141 @@
+
+
+
+
+
+
diff --git a/web/src/views/system/demo/index.vue b/web/src/views/system/demo/index.vue
index 4f7b7ec..4e71a9c 100644
--- a/web/src/views/system/demo/index.vue
+++ b/web/src/views/system/demo/index.vue
@@ -1,13 +1,80 @@
-
- 测试框架外显示
-
+
+
+
+
+
+
+
-
-
-