data_filter作为filterjson逻辑表达式,提取var构造搜索表单
This commit is contained in:
parent
b4ac434b62
commit
f00d95654c
@ -73,8 +73,7 @@ data_browser_tmpl = """
|
|||||||
{% if content_view %}
|
{% if content_view %}
|
||||||
"content_view":{{json.dumps(content_view, indent=4, ensure_ascii=False)}},
|
"content_view":{{json.dumps(content_view, indent=4, ensure_ascii=False)}},
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if search_fields %}
|
{% if data_filter %}
|
||||||
"search_fields":{{json.dumps(search_fields, indent=4, ensure_ascii=False)}},
|
|
||||||
"search_form":{
|
"search_form":{
|
||||||
"css":"card",
|
"css":"card",
|
||||||
"padding":"8px",
|
"padding":"8px",
|
||||||
@ -157,30 +156,14 @@ ns['sort'] = '{{relation.outter_field}}_text'
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
sql = '''{{sql}}'''
|
sql = '''{{sql}}'''
|
||||||
{% if not relation %}
|
{% if not relation %}
|
||||||
filterjson = params_kw.get('data_filter')
|
{% if data_filter %}
|
||||||
if filterjson and isinstance(filterjson, str):
|
filterjson = {{json.dumps(data_filter, ensure_ascii=False)}}
|
||||||
try:
|
{% else %}
|
||||||
filterjson = json.loads(filterjson)
|
filterjson = None
|
||||||
except (json.JSONDecodeError, TypeError):
|
|
||||||
filterjson = None
|
|
||||||
fields_str=r'''{{json.dumps(fields, indent=4, ensure_ascii=False)}}'''
|
fields_str=r'''{{json.dumps(fields, indent=4, ensure_ascii=False)}}'''
|
||||||
ori_fields = json.loads(fields_str)
|
ori_fields = json.loads(fields_str)
|
||||||
if not filterjson:
|
fields = [ f['name'] for f in ori_fields ]
|
||||||
fields = [ f['name'] for f in ori_fields ]
|
filterjson = default_filterjson(fields, ns)
|
||||||
filterjson = default_filterjson(fields, ns)
|
|
||||||
{% if search_fields %}
|
|
||||||
# 应用 search_fields 中显式声明的 op(如 LIKE)
|
|
||||||
__sf_ops = {f['field']: f.get('op') for f in {{json.dumps(search_fields, ensure_ascii=False)}} if f.get('op')}
|
|
||||||
if filterjson and __sf_ops:
|
|
||||||
if not isinstance(filterjson, dict) or 'AND' not in filterjson:
|
|
||||||
filterjson = {'AND': [filterjson] if filterjson else []}
|
|
||||||
for fj in filterjson['AND']:
|
|
||||||
if fj.get('field') in __sf_ops:
|
|
||||||
fj['op'] = __sf_ops[fj['field']]
|
|
||||||
if fj['op'] == 'LIKE':
|
|
||||||
var = fj.get('var')
|
|
||||||
if var and var in ns and ns[var]:
|
|
||||||
ns[var] = f'%{ns[var]}%'
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% if logined_userorgid or logined_userid %}
|
{% if logined_userorgid or logined_userid %}
|
||||||
# 确保 logined 过滤条件始终生效
|
# 确保 logined 过滤条件始终生效
|
||||||
|
|||||||
@ -255,50 +255,95 @@ def filter_backslash(s):
|
|||||||
ls = s.split('\\/')
|
ls = s.split('\\/')
|
||||||
return '/'.join(ls)
|
return '/'.join(ls)
|
||||||
|
|
||||||
|
def extract_filter_vars(filterjson, field_map):
|
||||||
|
"""递归提取 data_filter 中的 var 和对应的 field,返回 {var: field_info}"""
|
||||||
|
if not filterjson:
|
||||||
|
return {}
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
|
||||||
|
if isinstance(filterjson, dict):
|
||||||
|
# 逻辑操作符:AND, OR, NOT
|
||||||
|
for key in ['AND', 'OR', 'NOT', 'and', 'or', 'not']:
|
||||||
|
if key in filterjson:
|
||||||
|
sub = filterjson[key]
|
||||||
|
if isinstance(sub, list):
|
||||||
|
for item in sub:
|
||||||
|
result.update(extract_filter_vars(item, field_map))
|
||||||
|
elif isinstance(sub, dict):
|
||||||
|
result.update(extract_filter_vars(sub, field_map))
|
||||||
|
|
||||||
|
# 单个条件:field + op + var
|
||||||
|
if 'field' in filterjson and 'var' in filterjson:
|
||||||
|
var_name = filterjson['var']
|
||||||
|
field_name = filterjson['field']
|
||||||
|
if field_name in field_map:
|
||||||
|
result[var_name] = field_map[field_name].copy()
|
||||||
|
|
||||||
|
elif isinstance(filterjson, list):
|
||||||
|
for item in filterjson:
|
||||||
|
result.update(extract_filter_vars(item, field_map))
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
def build_filter_field_list(desc) -> list:
|
def build_filter_field_list(desc) -> list:
|
||||||
"""Build enriched filter field list for InlineForm search form.
|
"""从 data_filter 提取所有 var,根据 field 从 fields/alters 获取字段定义,
|
||||||
When a search_fields field has uitype='code', auto-populate
|
构造 InlineForm 搜索字段。field name 用 var。"""
|
||||||
valueField/textField/params/dataurl from the model's codes definition."""
|
if not desc.data_filter:
|
||||||
if not desc.search_fields:
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
# 构建 field name -> field info 的映射
|
||||||
|
field_map = {}
|
||||||
|
for f in field_list(desc):
|
||||||
|
field_map[f['name']] = f
|
||||||
|
|
||||||
|
# 从 data_filter 提取 var -> field info
|
||||||
|
var_field_map = extract_filter_vars(desc.data_filter, field_map)
|
||||||
|
|
||||||
codes_map = {}
|
codes_map = {}
|
||||||
if desc.codes:
|
if desc.codes:
|
||||||
for c in desc.codes:
|
for c in desc.codes:
|
||||||
cfield = c.field if isinstance(c, dict) else getattr(c, 'field', None)
|
cfield = c.field if isinstance(c, dict) else getattr(c, 'field', None)
|
||||||
if cfield:
|
if cfield:
|
||||||
codes_map[cfield] = c
|
codes_map[cfield] = c
|
||||||
|
|
||||||
modulename = getattr(desc, 'modulename', '')
|
modulename = getattr(desc, 'modulename', '')
|
||||||
result = []
|
result = []
|
||||||
for f in desc.search_fields:
|
|
||||||
field_name = f.field if isinstance(f, dict) else getattr(f, 'field', '')
|
for var_name, field_info in var_field_map.items():
|
||||||
field_title = f.title if isinstance(f, dict) else getattr(f, 'title', '')
|
field_name = field_info['name']
|
||||||
field_uitype = f.uitype if isinstance(f, dict) else getattr(f, 'uitype', 'str')
|
field_title = field_info.get('title', field_name)
|
||||||
|
field_uitype = field_info.get('uitype', 'str')
|
||||||
|
|
||||||
field_def = {
|
field_def = {
|
||||||
'name': field_name,
|
'name': var_name,
|
||||||
'uitype': field_uitype,
|
'uitype': field_uitype,
|
||||||
'placeholder': field_title,
|
'placeholder': field_title,
|
||||||
'cwidth': 15
|
'cwidth': 15
|
||||||
}
|
}
|
||||||
|
|
||||||
if field_uitype == 'code' and field_name in codes_map:
|
if field_uitype == 'code' and field_name in codes_map:
|
||||||
c = codes_map[field_name]
|
c = codes_map[field_name]
|
||||||
ctable = c.table if isinstance(c, dict) else getattr(c, 'table', '')
|
ctable = c.table if isinstance(c, dict) else getattr(c, 'table', '')
|
||||||
cvaluefield = c.valuefield if isinstance(c, dict) else getattr(c, 'valuefield', '')
|
cvaluefield = c.valuefield if isinstance(c, dict) else getattr(c, 'valuefield', '')
|
||||||
ctextfield = c.textfield if isinstance(c, dict) else getattr(c, 'textfield', '')
|
ctextfield = c.textfield if isinstance(c, dict) else getattr(c, 'textfield', '')
|
||||||
ccond = (c.cond if isinstance(c, dict) else getattr(c, 'cond', None))
|
ccond = (c.cond if isinstance(c, dict) else getattr(c, 'cond', None))
|
||||||
field_def['valueField'] = field_name
|
field_def['valueField'] = var_name
|
||||||
field_def['textField'] = field_name + '_text'
|
field_def['textField'] = var_name + '_text'
|
||||||
field_def['params'] = {
|
field_def['params'] = {
|
||||||
'dbname': "{{get_module_dbname('" + modulename + "')}}",
|
'dbname': "{{get_module_dbname('" + modulename + "')}}",
|
||||||
'table': ctable,
|
'table': ctable,
|
||||||
'tblvalue': cvaluefield,
|
'tblvalue': cvaluefield,
|
||||||
'tbltext': ctextfield,
|
'tbltext': ctextfield,
|
||||||
'valueField': field_name,
|
'valueField': var_name,
|
||||||
'textField': field_name + '_text'
|
'textField': var_name + '_text'
|
||||||
}
|
}
|
||||||
if ccond:
|
if ccond:
|
||||||
field_def['params']['cond'] = ccond
|
field_def['params']['cond'] = ccond
|
||||||
field_def['dataurl'] = "{{entire_url('/appbase/get_code.dspy')}}?prepend_all=1"
|
field_def['dataurl'] = "{{entire_url('/appbase/get_code.dspy')}}?prepend_all=1"
|
||||||
|
|
||||||
result.append(field_def)
|
result.append(field_def)
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def build_data_browser(pat: str, desc: dict):
|
def build_data_browser(pat: str, desc: dict):
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user