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