dvlyadmin_pro/backend/utils/autocode/lygeneratecode.py
2025-03-17 18:06:54 +08:00

298 lines
12 KiB
Python
Raw 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
# +-------------------------------------------------------------------
# | version:1.3
# +-------------------------------------------------------------------
# | Date: 2023-11-07
# +-------------------------------------------------------------------
# | django-vue-lyadmin
# +-------------------------------------------------------------------
# | Author: lybbn
# +-------------------------------------------------------------------
# | QQ: 1042594286
# +-------------------------------------------------------------------
# ------------------------------
# 代码生成
# ------------------------------
import os
import sys
from django.conf import settings
from django.core import management
from django.utils import autoreload
from mysystem.models import Menu,MenuButton,Role
from utils.autocode.template.lymodels import lyGenerateModels
from utils.autocode.template.lyserializer import lyGenerateSerializer
from utils.autocode.template.lyviewset import lyGenerateViewSet
from utils.autocode.template.lyurls import lyGenerateUrls
from utils.autocode.template.element.indexvue_lytable import lyGenerateIndexVue
from utils.autocode.template.lyfilters import lyGenerateFilters
class GenerateCode:
def __init__(self):
pass
def generate(self,object,mount=False,menu_instance=None,is_delete_file=False):
"""
is_delete_file:是否同时删除文件和相关菜单权限等
"""
data = []
models = lyGenerateModels(object)
data.append({
'code':models,
'file':'models.py',
})
serializer = lyGenerateSerializer(object)
data.append({
'code': serializer,
'file': 'serializer.py'
})
viewset = lyGenerateViewSet(object)
data.append({
'code': viewset,
'file': 'views.py'
})
filters = lyGenerateFilters(object)
data.append({
'code': filters,
'file': 'filters.py'
})
url_route_name = object['class_name']
base_url_path = "/api/autocode/"+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'
})
# apps = lyGenerateApps(object)
# data.append({
# 'code': apps,
# 'file': 'apps.py'
# })
VueIndexName = 'lyAutoCode%s'%object['class_name']
indexvue = lyGenerateIndexVue(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" % object['class_name']
models_name_old = "models_%s.py" % object['file_name_old']
self.check_exists_filename(models_path,models_name,object)
# serializer检测是否存在新生成的目标文件
serializer_path = self.generate_backend_filepath("serializers")
serializer_name = "serializer_%s.py" % object['class_name']
serializer_name_old = "serializer_%s.py" % object['file_name_old']
self.check_exists_filename(serializer_path,serializer_name, object)
# views检测是否存在新生成的目标文件
viewset_path = self.generate_backend_filepath("views")
viewset_name = "views_%s.py" % object['class_name']
viewset_name_old = "views_%s.py" % object['file_name_old']
self.check_exists_filename(viewset_path,viewset_name, object)
# filters检测是否存在新生成的目标文件
filters_path = self.generate_backend_filepath("filters")
filters_name = "filter_%s.py" % object['class_name']
filters_name_old = "filter_%s.py" % object['file_name_old']
self.check_exists_filename(filters_path,filters_name, object)
# urls检测是否存在新生成的目标文件
urls_path = self.generate_backend_filepath("urls")
urls_name = "urls_%s.py" % object['class_name']
urls_name_old = "urls_%s.py" % object['file_name_old']
self.check_exists_filename(urls_path,urls_name, object)
# 前端vue检测是否存在新生成的目标文件
indexvue_path = self.generate_frontend_filepath()
indexvue_name = '%s.vue' % VueIndexName
indexvue_name_old = "lyAutoCode%s.vue" % object['file_name_old']
self.check_exists_filename(indexvue_path,indexvue_name, object)
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(filters_path,filters_name)
self.delete_file(serializer_path,serializer_name)
self.delete_file(models_path,models_name)
self.delete_file(indexvue_path,indexvue_name)
self.delete_migrations(object)
return True
#modles创建文件
self.check_update_filename(models_path,models_name,models_name_old,object)
self.generate_file(models_path,models_name,models)
#serializer创建文件
self.check_update_filename(serializer_path,serializer_name, serializer_name_old, object)
self.generate_file(serializer_path,serializer_name,serializer)
#views创建文件
self.check_update_filename(viewset_path,viewset_name, viewset_name_old, object)
self.generate_file(viewset_path,viewset_name,viewset)
#filters创建文件
self.check_update_filename(filters_path,filters_name, filters_name_old, object)
self.generate_file(filters_path,filters_name,filters)
#urls创建文件
self.check_update_filename(urls_path,urls_name, urls_name_old, object)
self.generate_file(urls_path,urls_name,urls)
#前端vue创建文件
self.check_update_filename(indexvue_path,indexvue_name, indexvue_name_old, object)
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
def generate_backend_filepath(self,moduleName):
autoCodePath = os.path.join(settings.BASE_DIR, 'apps', 'lyautocode', moduleName)
return autoCodePath
def generate_frontend_filepath(self):
autoCodePath = os.path.join(os.path.abspath(os.path.join(settings.BASE_DIR,"..")),'frontend','src','views','lyAutoCodeManage')
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, 1]
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['db_table']
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='lyautocode' 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",'lyautocode'])
execute_from_command_line(["manage.py","migrate","--noinput","lyautocode"])
return True
return False
def syncdb(self):
try:
management.call_command("makemigrations","--noinput",'lyautocode')
management.call_command("migrate","--noinput","lyautocode")
return True
except Exception as e:
print("代码生成【同步数据库】出现异常,异常内容:%s"%e)
return False