项目文档辅助工具
本工具可以生成三个文档 数据库设计文档 、 接口文档 、 详细设计说明书 的部分内容,免去重复的文档编写工作,提高工作效率。
下载链接:工具下载地址
数据库设计文档
根据postgresql中的注释(字段注释 表注释)生成部分数据库设计文档内容
- 代码
import psycopg2
from docxtpl import DocxTemplate
# 连接数据库
def connect():
connect = psycopg2.connect(database="*_js_navigation", user="postgres", password="123456", host="172.16.11.*",
port="5432")
return connect
# 获取数据
def read_data(tabelName1, conn1, data1):
cur = conn1.cursor()
cur.execute(
"select cast(obj_description(relfilenode,'pg_class') as varchar) AS tabeName, "
"case when (FALSE = a.attnotnull) then '是' ELSE '否' END as is_null,a.attname "
"AS attname,concat_ws('',t.typname,SUBSTRING(format_type(a.atttypid,a.atttypmod) "
"from '\(.*\)')) as attype,d.description AS description from pg_class c,"
"pg_attribute a , pg_type t, pg_description d where c.relname = '" + tabelName1 +
"' and a.attnum>0 and a.attrelid = c.oid and a.atttypid = t.oid and d.objoid=a.attrelid"
" and d.objsubid=a.attnum ORDER BY c.relname DESC,a.attnum ASC")
rows = list(cur.fetchall())
if rows.__len__() == 0:
return
data_list = []
for row in rows:
comment1 = str(row[1])
comment2 = str(row[2])
comment3 = str(row[3])
comment4 = str(row[4])
temp = {
'columnCode': comment2,
'columnType': comment3,
'isNull': comment1,
'columnName': comment4,
}
data_list.append(temp)
tableName = rows[0][0]
if tableName is None:
tableName = '未知'
context = {
'tableCode': tabelName1,
'tableName': tableName,
'dataList': data_list
}
data1.append(context)
# 获取数据库表
def find_table_list(conn):
cur = conn.cursor()
cur.execute(
"select relname as tabname from pg_class c where relkind = 'r' and relname not like 'pg_%' and not relname like 'sql_%' and relchecks=0 order by relname")
rows = cur.fetchall()
data_list = []
for row in rows:
data_list.append(row[0])
return data_list
def do_write(conn1):
doc = DocxTemplate("数据库设计文档模板.docx") # 模板文档
data = []
table_list = find_table_list(conn1)
for table_name in table_list:
read_data(table_name, conn1, data)
doc.render({'data': data}) # 执行替换
doc.save("数据库设计文档.docx") # 保存新的文档
# 生成数据库设计文档
if __name__ == '__main__':
conn = connect()
do_write(conn)
conn.close()
- 文档模板
- 运行结果
接口文档
根据Torna地址(smart-doc)生成接口文档
- 代码
import requests
import json
from docxtpl import DocxTemplate
def my_sort(controller_data_list):
list_data_temp = []
data_temp = {}
i = 1
for controller_data in controller_data_list:
list_data = []
is_folder = controller_data['isFolder']
if is_folder == 1:
interface_id = controller_data['id']
controller_data['orderIndex'] = i
list_data.append(controller_data)
data_temp[interface_id] = list_data
i = i + 1
for controller_data in controller_data_list:
is_folder = controller_data['isFolder']
parent_id = controller_data['parentId']
if is_folder != 1:
list_data = data_temp.get(parent_id)
controller_data['orderIndex'] = list_data[0]['orderIndex']+1
list_data.append(controller_data)
data_temp[parent_id] = list_data
for key in data_temp:
list_data_temp = list_data_temp + data_temp[key]
list_data_temp = sorted(list_data_temp, key=lambda k: (k.get('orderIndex')))
return list_data_temp
def write(base_url, authorization, project_id):
if base_url == '':
base_url = 'http://IP:端口'
if authorization == '':
authorization = "Bearer L42GREzW:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" \
".eyJpZCI6IjU2IiwiZXhwIjoxNjc3NzM3MTYwLCJpYXQiOjE2NDYyMDExNjB9" \
".jReCTqjWKDEvkR9lC5x6jOdz9rL8NlnvRJK0XQCNqkk"
if project_id == '':
project_id = '7YX0llXx'
global interface_context_list, interface_temp_list
headers = {"Authorization": authorization}
# 获取模块
module_url = base_url + '/module/list'
module_params = {"projectId": project_id}
module_data = requests.get(url=module_url, params=module_params, headers=headers)
module_json_data = json.loads(module_data.text)
module_data_list = module_json_data["data"]
interface_temp_list = []
for module_data in module_data_list:
context = {}
module_name = module_data['name']
module_id = module_data['id']
context['module_name'] = module_name
# 获取接口列表
controller_url = base_url + '/doc/list'
controller_params = {"moduleId": module_id}
controller_data = requests.get(url=controller_url, params=controller_params, headers=headers)
controller_json_data = json.loads(controller_data.text)
controller_data_list = list(controller_json_data["data"])
controller_data_list = my_sort(controller_data_list)
# 接口
for controller_data in controller_data_list:
is_folder = controller_data['isFolder']
interface_name = controller_data['name']
interface_id = controller_data['id']
interface_context = {}
if is_folder == 1:
interface_context['interface_name'] = interface_name
interface_context_list = []
interface_context['interface_context_list'] = interface_context_list
interface_temp_list.append(interface_context)
continue
# 获取接口详情
interface_url = base_url + '/doc/view/detail'
interface_params = {"id": interface_id}
interface_data = requests.get(url=interface_url, params=interface_params, headers=headers)
interface_json_data = json.loads(interface_data.text)
interface_data = interface_json_data["data"]
function_description = str(interface_data["name"])
function_method = str(interface_data["httpMethod"])
function_envs = list(interface_data["debugEnvs"])
pre_url = 'Http://ip:port'
if function_envs.__len__() != 0:
pre_url = function_envs[0]['url']
function_url = pre_url + str(interface_data["url"])
# 请求参数
query_params = list(interface_data["queryParams"])
# requestParams 参数
query_params = query_params + list(interface_data["requestParams"])
# path参数
query_params = query_params + list(interface_data["pathParams"])
response_params = list(interface_data["responseParams"])
# 请求参数处理
params_list = []
if query_params.__len__() != 0:
for param in query_params:
required = '是' if param["required"] == 1 else '否'
function_params = {'name': param["name"], 'required': required, 'type': param["type"],
'description': param["description"]}
params_list.append(function_params)
else:
function_params = {'name': '', 'required': '', 'type': '', 'description': ''}
params_list.append(function_params)
# 响应参数处理
response_list = []
if response_params.__len__() != 0:
for param in response_params:
response_params = {'name': param["name"], 'example': param["example"], 'type': param["type"],
'description': param["description"]}
response_list.append(response_params)
else:
response_params = {'name': '', 'example': '', 'type': '', 'description': ''}
response_list.append(response_params)
interface = {
'function_url': function_url,
'function_method': function_method,
'query_params': params_list,
'function_description': function_description,
'response_list': response_list
}
interface_context_list.append(interface)
# print(interface_temp_list)
return interface_temp_list
def do_write(url, authorization, project_id):
doc = DocxTemplate("接口文档模板.docx") # 模板文档
data_list = write(url, authorization, project_id)
doc.render({"data": data_list}) # 执行替换
doc.save("接口文档.docx") # 保存新的文档
# 生成接口文档
if __name__ == '__main__':
do_write('', '', '')
- 文档模板
- 运行结果
详细设计说明书
根据Torna地址(smart-doc)生成部分详细设计说明书内容
- 代码
import requests
import json
from docxtpl import DocxTemplate
def my_sort(controller_data_list):
list_data_temp = []
data_temp = {}
i = 1
for controller_data in controller_data_list:
list_data = []
is_folder = controller_data['isFolder']
if is_folder == 1:
interface_id = controller_data['id']
controller_data['orderIndex'] = i
list_data.append(controller_data)
data_temp[interface_id] = list_data
i = i + 1
for controller_data in controller_data_list:
is_folder = controller_data['isFolder']
parent_id = controller_data['parentId']
if is_folder != 1:
list_data = data_temp.get(parent_id)
controller_data['orderIndex'] = list_data[0]['orderIndex']+1
list_data.append(controller_data)
data_temp[parent_id] = list_data
for key in data_temp:
list_data_temp = list_data_temp + data_temp[key]
list_data_temp = sorted(list_data_temp, key=lambda k: (k.get('orderIndex')))
return list_data_temp
def write(base_url, authorization, project_id):
if base_url == '':
base_url = 'http://IP:端口'
if authorization == '':
authorization = "Bearer L42GREzW:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" \
".eyJpZCI6IjU2IiwiZXhwIjoxNjc3NzM3MTYwLCJpYXQiOjE2NDYyMDExNjB9" \
".jReCTqjWKDEvkR9lC5x6jOdz9rL8NlnvRJK0XQCNqkk"
if project_id == '':
project_id = '7YX0llXx'
global interface_context_list, interface_temp_list
headers = {"Authorization": authorization}
# 获取模块
module_url = base_url + '/module/list'
module_params = {"projectId": project_id}
module_data = requests.get(url=module_url, params=module_params, headers=headers)
module_json_data = json.loads(module_data.text)
module_data_list = module_json_data["data"]
interface_temp_list = []
for module_data in module_data_list:
context = {}
module_name = module_data['name']
module_id = module_data['id']
context['module_name'] = module_name
# 获取接口列表
controller_url = base_url + '/doc/list'
controller_params = {"moduleId": module_id}
controller_data = requests.get(url=controller_url, params=controller_params, headers=headers)
controller_json_data = json.loads(controller_data.text)
controller_data_list = controller_json_data["data"]
# 接口
controller_data_list = my_sort(controller_data_list)
for controller_data in controller_data_list:
is_folder = controller_data['isFolder']
interface_name = controller_data['name']
interface_id = controller_data['id']
interface_context = {}
if is_folder == 1:
interface_context['interface_name'] = interface_name
interface_context_list = []
interface_context['interface_context_list'] = interface_context_list
interface_temp_list.append(interface_context)
continue
# 获取接口详情
interface_url = base_url + '/doc/view/detail'
interface_params = {"id": interface_id}
interface_data = requests.get(url=interface_url, params=interface_params, headers=headers)
interface_json_data = json.loads(interface_data.text)
interface_data = interface_json_data["data"]
function_url = str(interface_data["url"])
function_cn_name = str(interface_data["name"])
function_method = str(interface_data["httpMethod"])
function = function_url.split("/")
query_params = list(interface_data["queryParams"])
function_params = ""
if query_params.__len__() != 0:
for param in query_params:
function_params += param["name"] + "-" + param["type"] + " "
if function_params.__len__() == 0:
function_params = "-"
function_name = function[2] + "()"
interface = {
'function_name': function_name,
'function_method': function_method,
'function_params': function_params,
'function_cn_name': function_cn_name,
}
interface_context_list.append(interface)
# print(interface_temp_list)
return interface_temp_list
def do_write(url, authorization, project_id):
doc = DocxTemplate("详细设计说明书模板.docx") # 模板文档
data_list = write(url, authorization, project_id)
doc.render({"data": data_list}) # 执行替换
doc.save("详细设计说明文档.docx") # 保存新的文档
# 生成详细设计说明书文档
if __name__ == '__main__':
do_write('', '', '')
- 模板文档
- 运行结果
运行脚本 exe
import psycopg2
from filegenerator.database import database_file
from filegenerator.design import detail_design_file
from filegenerator.interface import Interface_file
# 连接数据库
def connect_pgsql():
host = input('PG数据库连接ip: (默认 127.0.0.1) ') #
if host == '':
host = 'IP'
user = input('PG数据库用户名: (默认 postgres) ') # 1
if user == '':
user = 'postgres'
password = input('PG数据库密码: (123456) ') # 'xtzGpdi123'
if password == '':
password = '123456'
database = input('目标数据的数据库: (默认 postgres) ') # 1
if database == '':
database = 'smart_js_navigation'
connect = psycopg2.connect(database=database, user=user, password=password, host=host,
port="5432")
return connect
# 连接smart_doc
def connect_smart_doc():
data_list = {}
url = input('Torna地址(smart-doc): (默认 http://IP:端口) ')
if url == '':
url = 'http://IP:端口'
authorization = input('Torna smart-doc验证信息 authorization: (默认 172.16.11.21的authorization) ')
if authorization == '':
authorization = "Bearer L42GREzW:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9" \
".eyJpZCI6IjU2IiwiZXhwIjoxNjc3NzM3MTYwLCJpYXQiOjE2NDYyMDExNjB9" \
".jReCTqjWKDEvkR9lC5x6jOdz9rL8NlnvRJK0XQCNqkk"
project_id = input('项目id: (默认 水上导航项目id) ')
if project_id == '':
project_id = '7YX0llXx'
data_list['url'] = url
data_list['authorization'] = authorization
data_list['project_id'] = project_id
return data_list
# pyinstaller -F file_main.py 打包成exe执行文件命令
if __name__ == '__main__':
print('解释说明:')
print('本程序可以生成三个文档 01 数据库设计文档 02 接口文档 03 详细设计说明书 ')
print('数据库文档只支持postgresql 接口文档、详细设计说明书需要用Torna地址(smart-doc)')
file_type = input("请输入要生成的文档类型(01:数据库设计文档 02:接口文档 03:详细设计说明书 04:全部文档):")
if file_type == '01':
connect = connect_pgsql()
# 数据库设计文档
database_file.do_write(connect)
connect.close()
elif file_type == '02':
smart_doc = connect_smart_doc()
url = smart_doc['url']
project_id = smart_doc['project_id']
authorization = smart_doc['authorization']
# 接口文档
Interface_file.do_write(url, authorization, project_id)
elif file_type == '03':
smart_doc = connect_smart_doc()
url = smart_doc['url']
project_id = smart_doc['project_id']
authorization = smart_doc['authorization']
# 详细设计说明书
detail_design_file.do_write(url, authorization, project_id)
elif file_type == '04':
connect = connect_pgsql()
# 数据库设计文档
database_file.do_write(connect)
connect.close()
smart_doc = connect_smart_doc()
url = smart_doc['url']
project_id = smart_doc['project_id']
authorization = smart_doc['authorization']
# 接口文档
Interface_file.do_write(url, authorization, project_id)
# 详细设计说明书
detail_design_file.do_write(url, authorization, project_id)
else:
print('请输入正确类型(01:数据库设计文档 02:接口文档 03:详细设计说明书 04:全部文档)')
- 通过 pyinstaller -F file_main.py 打包成exe执行文件命令
- 运行
- 运行结果
帮助理解
-
项目id(project_id):
-
项目地址(Torna地址(smart-doc)):
-
验证信息(Torna smart-doc验证信息 authorization)
登录Torna之后,按F12打开开发者工具,刷新页面,找到请求头中的Authorization值