refactor: 外键字段过滤支持 / filter_fields支持配置lookup_prefixes

pull/102/head
Angelo 2023-07-14 04:15:15 +08:00
parent 8394f92178
commit dbcbf117bb
3 changed files with 64 additions and 24 deletions

View File

@ -249,16 +249,16 @@ class UserViewSet(CustomModelViewSet):
serializer_class = UserSerializer serializer_class = UserSerializer
create_serializer_class = UserCreateSerializer create_serializer_class = UserCreateSerializer
update_serializer_class = UserUpdateSerializer update_serializer_class = UserUpdateSerializer
# filter_fields = ["name", "username", "gender", "is_active", "dept", "user_type"] filter_fields = ["^name", "~username", "^mobile", "is_active", "dept", "user_type", "$dept__name"]
filter_fields = { # filter_fields = {
"name": ["icontains"], # "name": ["icontains"],
"mobile": ["icontains"], # "mobile": ["icontains"],
"username": ["icontains"], # "username": ["icontains"],
"gender": ["icontains"], # "gender": ["icontains"],
"is_active": ["icontains"], # "is_active": ["icontains"],
"dept": ["exact"], # "dept": ["exact"],
"user_type": ["exact"], # "user_type": ["exact"],
} # }
search_fields = ["username", "name", "gender", "dept__name", "role__name"] search_fields = ["username", "name", "gender", "dept__name", "role__name"]
# 导出 # 导出
export_field_label = { export_field_label = {

View File

@ -150,6 +150,7 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
"$": "iregex", "$": "iregex",
"~": "icontains", "~": "icontains",
} }
filter_fields = "__all__"
def construct_search(self, field_name, lookup_expr=None): def construct_search(self, field_name, lookup_expr=None):
lookup = self.lookup_prefixes.get(field_name[0]) lookup = self.lookup_prefixes.get(field_name[0])
@ -157,19 +158,32 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
field_name = field_name[1:] field_name = field_name[1:]
else: else:
lookup = lookup_expr lookup = lookup_expr
if lookup:
if field_name.endswith(lookup): if field_name.endswith(lookup):
return field_name return field_name
return LOOKUP_SEP.join([field_name, lookup]) return LOOKUP_SEP.join([field_name, lookup])
return field_name
def find_filter_lookups(self, orm_lookups, search_term_key): def find_filter_lookups(self, orm_lookups, search_term_key):
for lookup in orm_lookups: for lookup in orm_lookups:
# if lookup.find(search_term_key) >= 0: # 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 # 修复条件搜索错误 bug
if new_lookup == search_term_key: if new_lookup == search_term_key:
return lookup return lookup
return None return None
# CASE: 前端query string过滤
# def find_filter_lookups(self, orm_lookups, search_term_key):
# for lookup, lookup_expr in orm_lookups.items():
# # if lookup.find(search_term_key) >= 0:
# search_key = self.construct_search(search_term_key, lookup_expr)
# new_lookup = LOOKUP_SEP.join(search_key.split(LOOKUP_SEP)[:-1]) if len(search_key.split(LOOKUP_SEP)) > 1 else lookup
# # 修复条件搜索错误 bug
# if new_lookup == lookup:
# return search_key
# return None
def get_filterset_class(self, view, queryset=None): def get_filterset_class(self, view, queryset=None):
""" """
Return the `FilterSet` class used to filter the queryset. Return the `FilterSet` class used to filter the queryset.
@ -189,7 +203,13 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
utils.deprecate( 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: if filterset_class:
filterset_model = filterset_class._meta.model filterset_model = filterset_class._meta.model
@ -327,14 +347,17 @@ class CustomDjangoFilterBackend(DjangoFilterBackend):
return queryset return queryset
if filterset.__class__.__name__ == "AutoFilterSet": if filterset.__class__.__name__ == "AutoFilterSet":
queryset = filterset.queryset queryset = filterset.queryset
orm_lookups = [] # orm_lookups = []
for search_field in filterset.filters: # for search_field in filterset.filters:
if isinstance(filterset.filters[search_field], CharFilter): # if isinstance(filterset.filters[search_field], CharFilter):
orm_lookups.append( # orm_lookups.append(
self.construct_search(six.text_type(search_field), filterset.filters[search_field].lookup_expr) # self.construct_search(six.text_type(search_field), filterset.filters[search_field].lookup_expr)
) # )
else: # else:
orm_lookups.append(search_field) # orm_lookups.append(search_field)
orm_lookups = [self.construct_search(str(search_field)) for search_field in self.filter_fields]
# CASE: 前端query string过滤
# orm_lookups = {lookup: filterset.filters[lookup].lookup_expr for lookup in filterset.filters.keys()}
conditions = [] conditions = []
queries = [] queries = []
for search_term_key in filterset.data.keys(): for search_term_key in filterset.data.keys():

View File

@ -92,6 +92,23 @@ export const crudOptions = (vm) => {
disabled: true disabled: true
} }
}, },
{
title: '部门名称',
key: 'dept__name',
treeNode: true, // 设置为树形列
search: {
disabled: false,
component: {
props: {
clearable: true
}
}
},
show: false,
form: {
disabled: true
}
},
{ {
title: '账号', title: '账号',
key: 'username', key: 'username',
@ -174,7 +191,7 @@ export const crudOptions = (vm) => {
title: '部门', title: '部门',
key: 'dept', key: 'dept',
search: { search: {
disabled: true disabled: false
}, },
minWidth: 140, minWidth: 140,
type: 'tree-selector', type: 'tree-selector',