2025-03-18 08:46:50 +08:00

316 lines
14 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/python
#coding: utf-8
# +-------------------------------------------------------------------
# | django-vue-lyadmin 专业版
# +-------------------------------------------------------------------
# | Author: lybbn
# +-------------------------------------------------------------------
# | QQ: 1042594286
# +-------------------------------------------------------------------
# | Date: 2023-11-07
# +-------------------------------------------------------------------
# | version: v1.5
# +-------------------------------------------------------------------
# ------------------------------
# 表单构建
# ------------------------------
import os
import sys
import json
from django.conf import settings
from django.core import management
from django.utils import autoreload
from mysystem.models import Menu,MenuButton
from utils.lyformbuilder.template.lymodels import lyGenerateModels
from utils.lyformbuilder.template.lyviewset import lyGenerateViewSet
from utils.lyformbuilder.template.lyurls import lyGenerateUrls
from utils.lyformbuilder.template.element.indexvue_lytable import lyGenerateIndexVue
class GenerateCode:
def __init__(self):
pass
def generate(self,objects,mount=False,menu_instance=None,is_delete_file=False):
"""
is_delete_file:是否同时删除文件和相关菜单权限等
"""
data = []
object = {}#处理后的需要的后台字段
object['formConfig'] = objects['formConfig']
object['widgetList'] = self.filterFormField(objects['widgetList'])
if len(object['widgetList']) <1:
raise ValueError("暂无可生成的CRUD配置")
models = lyGenerateModels(object)
data.append({
'code':models,
'file':'models.py',
})
viewset = lyGenerateViewSet(object)
data.append({
'code': viewset,
'file': 'views.py'
})
url_route_name = object['formConfig']['modelClassName']
base_url_path = "/api/lyformbuilder/"+url_route_name+"/"
api_list = [base_url_path,base_url_path,base_url_path+"{id}/",base_url_path+"{id}/",base_url_path+"{id}/",base_url_path+"export/"]
urls = lyGenerateUrls(object)
data.append({
'code': urls,
'file': 'urls.py'
})
VueIndexName = 'lyFormBuilder%s'%object['formConfig']['modelClassName']
indexvue = lyGenerateIndexVue(json.dumps(objects),object,VueIndexName)
data.append({
'code': indexvue,
'file': '%s.vue'%VueIndexName
})
if not mount:#预览代码
return data
if not settings.DEBUG:
raise ValueError("当前非debug状态不支持生成")
# modles检测是否存在新生成的目标文件
models_path = self.generate_backend_filepath("models")
models_name = "models_%s.py" % objects['class_name']
models_name_old = "models_%s.py" % objects['file_name_old']
self.check_exists_filename(models_path,models_name,objects)
# views检测是否存在新生成的目标文件
viewset_path = self.generate_backend_filepath("views")
viewset_name = "views_%s.py" % objects['class_name']
viewset_name_old = "views_%s.py" % objects['file_name_old']
self.check_exists_filename(viewset_path,viewset_name, objects)
# urls检测是否存在新生成的目标文件
urls_path = self.generate_backend_filepath("urls")
urls_name = "urls_%s.py" % objects['class_name']
urls_name_old = "urls_%s.py" % objects['file_name_old']
self.check_exists_filename(urls_path,urls_name, objects)
# 前端vue检测是否存在新生成的目标文件
indexvue_path = self.generate_frontend_filepath()
indexvue_name = '%s.vue' % VueIndexName
indexvue_name_old = "lyFormBuilder%s.vue" % objects['file_name_old']
self.check_exists_filename(indexvue_path,indexvue_name, objects)
if is_delete_file:
self.delete_menu_button(menu_instance)
self.delete_file(urls_path,urls_name)
self.delete_file(viewset_path,viewset_name)
self.delete_file(models_path,models_name)
self.delete_file(indexvue_path,indexvue_name)
self.delete_migrations(objects)
return True
#modles创建文件
self.check_update_filename(models_path,models_name,models_name_old,objects)
self.generate_file(models_path,models_name,models)
#views创建文件
self.check_update_filename(viewset_path,viewset_name, viewset_name_old, objects)
self.generate_file(viewset_path,viewset_name,viewset)
#urls创建文件
self.check_update_filename(urls_path,urls_name, urls_name_old, objects)
self.generate_file(urls_path,urls_name,urls)
#前端vue创建文件
self.check_update_filename(indexvue_path,indexvue_name, indexvue_name_old, objects)
self.generate_file(indexvue_path,indexvue_name,indexvue)
#配置路由菜单(外层已配置)
#配置按钮权限
if menu_instance:
self.create_update_menu_button(menu_instance,api_list)
# #同步数据库
# self.sync_db()
return True
#过滤form字段
def filterFormField(self,obj,data_list=None):
if data_list is None:
data_list = []
for o in obj:
if o.get('type',None) == 'grid' and o.get('category',None) == 'container':
for c in o['cols']:
if c.get('formItemFlag',False) and c.get('options').get('isFormField'):
data_list.append(c)
continue
else:
self.filterFormField([c],data_list)
elif o.get('type',None) == 'grid-col' and o.get('category',None) == 'container':
for c in o['widgetList']:
if c.get('formItemFlag',False) and c.get('options').get('isFormField'):
data_list.append(c)
continue
else:
self.filterFormField([c],data_list)
elif o.get('type',None) == 'table' and o.get('category',None) == 'container':
for c in o['rows']:
if len(c)>0:
for cc in c['cols']:
if len(cc)>0:
for w in cc['widgetList']:
if w.get('formItemFlag',False) and w.get('options').get('isFormField'):
data_list.append(w)
continue
else:
self.filterFormField([w],data_list)
elif o.get('type',None) == 'tab' and o.get('category',None) == 'container':
for c in o['tabs']:
if len(c)>0:
for w in c['widgetList']:
if w.get('formItemFlag',False) and w.get('options').get('isFormField'):
data_list.append(w)
continue
else:
self.filterFormField([w],data_list)
elif o.get('type',None) == 'card' and o.get('category',None) == 'container':
for w in o['widgetList']:
if w.get('formItemFlag',False) and w.get('options').get('isFormField'):
data_list.append(w)
continue
else:
self.filterFormField([w],data_list)
else:
if o.get('formItemFlag',False) and o.get('options').get('isFormField'):
data_list.append(o)
return data_list
def generate_backend_filepath(self,moduleName):
autoCodePath = os.path.join(settings.BASE_DIR, 'apps', 'lyFormBuilder', moduleName)
return autoCodePath
def generate_frontend_filepath(self):
autoCodePath = os.path.join(os.path.abspath(os.path.join(settings.BASE_DIR,"..")),'frontend','src','views','lyFormBuilderManage')
return autoCodePath
def check_exists_filename(self,path,filename,object):
"""
filename 新文件名
filename_old 原文件名
"""
if not object['file_name_old']:
raise ValueError("field file_name_old error")
if not object['class_name'] == object['file_name_old']:
if os.path.exists(os.path.join(path, filename)):
raise ValueError("检测生成文件错误,已存在%s文件" % filename)
def check_update_filename(self,path,filename,filename_old,object):
"""
filename 新文件名
filename_old 原文件名
"""
if not object['file_name_old']:
raise ValueError("field file_name_old error")
if not object['class_name'] == object['file_name_old']:
if os.path.exists(os.path.join(path, filename)):
raise ValueError("生成文件错误,已存在%s文件" % filename)
if os.path.exists(os.path.join(path, filename_old)):
os.rename(os.path.join(path, filename_old),os.path.join(path, filename))
def generate_file(self,path,filename,content):
# 创建app文件夹
if not os.path.exists(path):
# 如果目标路径不存在就创建
os.makedirs(path)
with open(os.path.join(path, filename), 'w', encoding='UTF-8') as f:#w覆盖,a追加
f.write(content)
def create_update_menu_button(self,menu,api_list):
button_name_list = ["查询", "新增", "编辑", "删除", "单例","导出"] # (0, "GET"),(1, "POST"),(2, "PUT"),(3, "DELETE")
crud_button = ['Search','Create','Update','Delete','Retrieve',"Export"]
button_name_num_list = [0, 1, 2, 3, 0]
menubutton_queryset = MenuButton.objects.filter(menu=menu,name__in=button_name_list)
if menubutton_queryset.count() == 0:
intance_list = []
for index,value in enumerate(button_name_list):
obj = MenuButton(menu=menu, name=value, value=crud_button[index],method=button_name_num_list[index],api=api_list[index])
intance_list.append(obj)
MenuButton.objects.bulk_create(intance_list)
else:
for m in menubutton_queryset:
for i,c in enumerate(crud_button):
if m.value == c:
m.api = api_list[i]
m.save()
#删除菜单、按钮、权限
def delete_menu_button(self,menu):
print('删除文件>>> 删除菜单、按钮、权限')
if menu:
Menu.objects.filter(id=menu.id).delete()
def delete_file(self,path,filename):
try:
print('删除文件>>> ', filename)
os.remove(os.path.join(path, filename))
except:
pass
def get_file_list(self,directory):
return [f for f in os.listdir(directory) if os.path.isfile(os.path.join(directory, f))]
#删除迁移相关
def delete_migrations(self,object):
class_name = object['class_name']
db_table = object['formConfig']['modelDbTable']
lower_class_name = class_name.lower()
contains_str = "_"+lower_class_name
from django.db import connection
with connection.cursor() as cursor:
print('删除表和迁移数据>>> ', db_table)
cursor.execute("DELETE FROM django_migrations WHERE app='lyFormBuilder' AND name LIKE '%s'"%("%"+contains_str+"%"))
cursor.execute("DROP TABLE IF EXISTS %s"%db_table)
migrationsPath = self.generate_backend_filepath("migrations")
files = self.get_file_list(migrationsPath)
for file_k in files:
if file_k != '__init__.py' and contains_str in file_k:
dst_file = os.path.join(migrationsPath, file_k)
try:
print('删除文件>>> ', dst_file)
os.remove(dst_file)
except:
pass
#重载
def reload_server(self):
autoreload.restart_with_reloader()
def sync_db(self):
if settings.DEBUG:
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'application.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
raise ImportError(
"Couldn't import Django. Are you sure it's installed and "
"available on your PYTHONPATH environment variable? Did you "
"forget to activate a virtual environment?"
) from exc
execute_from_command_line(["manage.py","makemigrations","--noinput",'lyFormBuilder'])
execute_from_command_line(["manage.py","migrate","--noinput","lyFormBuilder"])
def syncdb(self):
try:
management.call_command("makemigrations","--noinput",'lyFormBuilder')
management.call_command("migrate","--noinput","lyFormBuilder")
return True
except Exception as e:
print("表单构建【同步数据库】出现异常,异常内容:%s"%e)
return False