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 None: data.pop('default', None) data['required'] = True elif default == '': data['required'] = False data['allow_blank'] = True else: data['required'] = False data = set_default_by_type(field_type, data, field_info) data = set_default_if_need(data, i) if field_type in ['int', 'bool', 'list'] and "allow_blank" in data.keys(): data.pop('allow_blank') 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)