You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
jumpserver/apps/common/serializers/dynamic.py

66 lines
2.1 KiB

from rest_framework import serializers
example_info = [
{"name": "name", "label": "姓名", "required": False, "default": "广州老广", "type": "str"},
{"name": "age", "label": "年龄", "required": False, "default": 18, "type": "int"},
]
type_field_map = {
"str": serializers.CharField,
"password": serializers.CharField,
"int": serializers.IntegerField,
"bool": serializers.BooleanField,
"text": serializers.CharField,
"choice": serializers.ChoiceField,
"list": serializers.ListField,
}
def set_default_if_need(data, i):
field_name = data.pop('name', 'Attr{}'.format(i + 1))
data['name'] = field_name
if not data.get('label'):
data['label'] = field_name
return data
def set_default_by_type(tp, data, field_info):
if tp == 'str':
data['max_length'] = 4096
elif tp == 'password':
data['write_only'] = True
elif tp == 'choice':
choices = field_info.pop('choices', [])
if isinstance(choices, str):
choices = choices.split(',')
choices = [
(c, c.title()) if not isinstance(c, (tuple, list)) else c
for c in choices
]
data['choices'] = choices
return data
def create_serializer_class(serializer_name, fields_info):
serializer_fields = {}
fields_name = ['name', 'label', 'default', 'required', 'type', 'help_text']
for i, field_info in enumerate(fields_info):
data = {k: field_info.get(k) for k in fields_name}
field_type = data.pop('type', 'str')
# 用户定义 default 和 required 可能会冲突, 所以要处理一下
default = data.get('default', None)
if default is not None:
data['required'] = False
else:
data.pop('default', None)
data['required'] = True
data = set_default_by_type(field_type, data, field_info)
data = set_default_if_need(data, i)
field_name = data.pop('name')
field_class = type_field_map.get(field_type, serializers.CharField)
serializer_fields[field_name] = field_class(**data)
return type(serializer_name, (serializers.Serializer,), serializer_fields)