import json from apps.lyFormBuilder.models.models_lyFormBuilder import * from utils.jsonResponse import SuccessResponse,DetailResponse,ErrorResponse from utils.common import get_parameter_dic, ast_convert,starts_with_digit from utils.models import is_table_exists from rest_framework import serializers from utils.serializers import CustomModelSerializer from utils.viewset import CustomModelViewSet from utils.lyformbuilder.lygeneratecode import GenerateCode from django.db.models import Q from django.db import transaction import logging logger = logging.getLogger(__name__) class lyFormBuilderSerializer(CustomModelSerializer): """ 表单构建 -序列化器 """ def to_representation(self, instance): # 序列化 ret = super().to_representation(instance) ret['formJson'] = ast_convert(ret['formJson']) # 可以保存的修改字段值的方法 return ret class Meta: model = lyFormBuilder read_only_fields = ["id"] fields = '__all__' class lyFormBuilderCreateUpdateSerializer(CustomModelSerializer): """ 表单构建 -序列化器 """ formJson = serializers.JSONField() class Meta: model = lyFormBuilder read_only_fields = ["id"] fields = '__all__' class lyFormBuilderViewSet(CustomModelViewSet): """ 后台表单构建 接口: """ queryset = lyFormBuilder.objects.filter(is_delete=False).order_by('-create_datetime') serializer_class = lyFormBuilderSerializer create_serializer_class = lyFormBuilderCreateUpdateSerializer update_serializer_class = lyFormBuilderCreateUpdateSerializer search_fields = ('class_name','verbose_name','db_table') # 重写delete方法,并改为逻辑删除 def destroy(self, request, *args, **kwargs): real_delete = get_parameter_dic(request).get('real_delete',None) instance = self.get_object_list() if not real_delete: for i in range(len(instance)): instance[i].is_delete = True model = self.get_serializer().Meta.model model.objects.bulk_update(instance, fields=['is_delete']) return SuccessResponse(data=[], msg="删除成功") else: for i in range(len(instance)): serializer = self.get_serializer(instance[i]) object = serializer.data if instance[i].is_mount: menu_instance = None if instance[i].menu: menu_instance = instance[i].menu newObject = json.loads(json.dumps(object['formJson'])) newObject['class_name'] = object['class_name'] newObject['file_name_old'] = object['file_name_old'] GenerateCode().generate(newObject, True, menu_instance,True) self.perform_destroy(instance) return DetailResponse(msg="删除成功") def create(self, request, *args, **kwargs): params = request.data class_name = params.get('class_name',None) if starts_with_digit(class_name): return ErrorResponse(msg="类名【%s】不能以数字开头!!!"%class_name) db_table = params.get('db_table', None) if not all([class_name,db_table]): return ErrorResponse(msg="请先填写表单CRUD属性") if self.filter_queryset(self.get_queryset()).filter(Q(class_name=class_name)|Q(db_table=db_table)).exists(): return ErrorResponse(msg="存在同名的类名或表名") if is_table_exists(db_table): return ErrorResponse(msg="存在同名的表名,请更改后再试") formJson = ast_convert(params.get('formJson', None)) if not formJson or not len(formJson['widgetList'])>0: return ErrorResponse(msg="表单至少拥有一个组件") params['parent_menu'] = 35#系统工具 params['file_name_old'] = class_name serializer = self.get_serializer(data=params, request=request) serializer.is_valid(raise_exception=True) self.perform_create(serializer) return DetailResponse(data=serializer.data, msg="新增成功") def editMenu(self,request): """ 菜单配置 """ params = request.data parent_menu = params.get('parent_menu',None) id = params.get('id',None) menu_sort = params.get('menu_sort',88) queryset = self.filter_queryset(self.get_queryset()) instance = queryset.filter(id=id).first() if not instance: return ErrorResponse(msg="id error or no permission") instance.parent_menu = parent_menu instance.menu_sort = menu_sort instance.save() return DetailResponse(msg="更新成功") def previewCodeFormJSON(self,request): """ 根据前端传递form表单json数据预览生成代码 """ formJson = ast_convert(get_parameter_dic(request).get('formJson',None)) if not formJson: return ErrorResponse(msg="参数错误") if formJson['formConfig']['jsonVersion'] !=1: return ErrorResponse(msg="版本错误") if formJson['formConfig']['modelClassName'] == "" or formJson['formConfig']['modelDbTable'] == "" or formJson['formConfig']['modelVerboseName'] == "": return SuccessResponse(data=[],total=0) data = GenerateCode().generate(formJson) return SuccessResponse(data=data,total=len(data)) def generateMount(self,request): id = get_parameter_dic(request).get('id',None) instance = self.filter_queryset(self.get_queryset()).filter(id=id).first() if not instance: return ErrorResponse(msg="id error") serializer = self.get_serializer(instance) object = serializer.data # vue的route name VueIndexName = 'lyFormBuilder%s' % object['class_name'] try: # 在事务开始前创建保存点 save_id = transaction.savepoint() # 以下代码会在事务中执行 # 配置路由菜单 if instance.menu: menu_instance = instance.menu Menu.objects.filter(id=menu_instance.id).update(name=object['verbose_name'], web_path=VueIndexName,sort=object['menu_sort'],parent_id=object['parent_menu']) else: menu_instance,created = Menu.objects.get_or_create(name=object['verbose_name'], sort=object['menu_sort'],web_path=VueIndexName, isautopm=1) if object['parent_menu']: menu_instance.parent_id = object['parent_menu'] menu_instance.save() instance.menu = menu_instance instance.save() newObject = json.loads(json.dumps(object['formJson'])) newObject['class_name'] = object['class_name'] newObject['file_name_old'] = object['file_name_old'] data = GenerateCode().generate(newObject, True, menu_instance) if not data: # 回滚到保存点 transaction.savepoint_rollback(save_id) return ErrorResponse(msg="生成文件错误") instance.file_name_old = object['class_name'] instance.is_mount = True instance.save() # 提交从保存点到当前状态的所有数据库事务操作 transaction.savepoint_commit(save_id) return DetailResponse(msg="操作成功") except Exception as e: # 回滚到保存点 transaction.savepoint_rollback(save_id) # 处理代码 raise e def syncdb(self,request): result = GenerateCode().syncdb() if result: return DetailResponse(msg="数据库同步成功") return ErrorResponse(msg="数据库同步失败,请查看后端IDE报错内容,或重启后端项目重试同步")