298 lines
12 KiB
Python
298 lines
12 KiB
Python
#!/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 |