当前位置:网站首页>django model生成docx数据库设计文档
django model生成docx数据库设计文档
2022-06-29 03:22:00 【徒余途】
django项目数据库设计文档生成
直接上代码
使用说明
按照步骤 TODO1、TODO2、TODO3 之后运行文件,数据库设计文档生成在当前目录下
# Desc : django项目生成doc文档
# TODO 注: model的Meta属性和字段属性记得添加verbose_name属性,apps.py需要添加verbose_name
# TODO 1. 复制项目DJANGO_SETTINGS_MODULE的值
# TODO 2. 在项目settings.py中配置 PROJECT_NAME(项目名称)
# TODO 3. 需要修改此自建app的列表 model_doc_apps的值
import os
import sys
import django
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# TODO 1 复制项目DJANGO_SETTINGS_MODULE的值 替换 radio_station_design.settings
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "radio_station_design.settings")
django.setup()
# TODO 3 需要导出的model模块
model_doc_apps = ['usermanage', 'station', ]
from django.apps import apps
# TODO 2 导入PROJECT_NAME(自定义项目名称)
from radio_station_design.settings import PROJECT_NAME
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.shared import Inches, Pt, RGBColor
from datetime import datetime
class MyDoc:
"""生成docx文档"""
def __init__(self, out_path, project_name='项目名称'):
self.project_name = project_name
self.out_path = out_path
self._get_doc()
def _get_doc(self):
self.document = Document()
def add_heading(self, head, level=1):
"""自定义的标题格式"""
# heading = self.document.add_heading(head, level)
if not 0 <= level <= 9:
raise ValueError("level must be in range 0-9, got %d" % level)
style = "Title" if level == 0 else "Heading %d" % level
p = self.document.add_paragraph(style=style)
space_size = 11 - level
# 段前间距
p.paragraph_format.space_before = Pt(space_size)
# 段后间距
p.paragraph_format.space_after = Pt(space_size)
p_run = p.add_run(head)
p_run.font.name = u"仿宋"
if level:
p_run.font.color.rgb = RGBColor(0, 68, 136)
# 加粗
p_run.bold = True
# 字体大小
font_size = 28 - level * 2
p_run.font.size = Pt(font_size)
return p
def set_title(self):
"""设置标题以及生成日期"""
title = self.document.add_heading(self.project_name + "数据库设计", 0)
title.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
p = self.document.add_paragraph()
p.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.RIGHT
# 右侧缩进
p.paragraph_format.right_indent = Pt(4)
pp = p.add_run("文档生成时间:" + datetime.now().strftime("%Y-%m-%d"))
pp.font.size = Pt(16)
def generate_doc(self):
"""生成文档固定部分"""
# 生成doc文档
self.set_title()
self.add_heading('引言', level=1)
self.add_paragraph("")
self.add_heading('关于', level=1)
self.add_paragraph(f"此文档主要介绍{
self.project_name}数据库定义。")
self.add_heading('目标读者', level=1)
self.add_paragraph("此文档提供给软件开发人员和系统维护人员使用。")
self.add_heading('术语定义', level=1)
self.add_paragraph("")
self.add_heading('参考资料', level=1)
self.add_paragraph("")
self.add_heading('数据库设计', level=1)
def add_model(self, model_name='model名称', table_name="table_name", data=[]):
"""添加model生成doc部分"""
self.add_heading(model_name, level=3)
self.add_paragraph("表名:" + table_name)
if len(data) == 0:
return
table = self.document.add_table(rows=1, cols=7, style='Medium List 1 Accent 1')
table.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
table.autofit = True
header_cells = table.rows[0].cells
table.rows[0].height = Inches(0.5)
header_cells[0].text = '字段名称'
header_cells[1].text = '中文含义'
header_cells[2].text = '数据类型'
header_cells[3].text = '不为空'
header_cells[4].text = '默认值'
header_cells[5].text = '键值'
header_cells[6].text = '备注'
header_cells[0].width = Inches(1.5)
header_cells[1].width = Inches(1.5)
header_cells[2].width = Inches(1.25)
header_cells[3].width = Inches(0.75)
header_cells[4].width = Inches(1)
header_cells[5].width = Inches(0.8)
header_cells[6].width = Inches(2)
for d0, d1, d2, d3, d4, d5, d6 in data:
row = table.add_row()
row.height = Inches(0.3)
row_cells = row.cells
row_cells[0].text = str(d0)
row_cells[1].text = str(d1)
row_cells[2].text = str(d2)
row_cells[3].text = str(d3)
row_cells[4].text = str(d4)
row_cells[5].text = str(d5)
row_cells[6].text = str(d6)
self.set_cells_border(table)
self.set_cells_text_alignment(table)
self.add_paragraph("")
def set_cells_text_alignment(self, table):
"""给table设置居中格式或其他"""
for row in range(len(table.rows)):
for col in range(len(table.columns)):
# 水平居中
# table.cell(row, col).paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
# 垂直居中
table.cell(row, col).vertical_alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
def set_cell_value(self, cell, value):
"""给单个cell赋值,以及格式"""
cell.text = str(value)
# 水平居中
# cell.paragraphs[0].alignment=WD_PARAGRAPH_ALIGNMENT.CENTER
# 垂直居中
cell.vertical_alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
pass
def add_app_name(self, app_name='模块名称'):
"""添加模块名称"""
self.add_heading(app_name, level=2)
def _close_doc(self):
self.document.save(self.out_path)
def make_doc(self):
self._close_doc()
def add_paragraph(self, text):
"""添加段落以及设置格式"""
p = self.document.add_paragraph()
# 左侧缩进
p.paragraph_format.left_indent = Pt(4)
# 右侧缩进
p.paragraph_format.right_indent = Pt(4)
# 首行缩进
# p.paragraph_format.first_line_indent = Inches(0.25)
# 行间距
p.paragraph_format.line_spacing = Pt(18)
# 段前间距
p.paragraph_format.space_before = Pt(7)
# 段后间距
p.paragraph_format.space_after = Pt(15)
p_run = p.add_run(text)
p_run.font.name = u"仿宋"
p_run.font.size = Pt(14)
# 加粗
# p.add_run('bold').bold = True
# p.add_run(' and some ')
# 斜体
# p.add_run('italic.').italic = True
def add_picture(self, pic_path):
self.document.add_picture('monty-truth.png', width=Inches(1.25))
def add_table(self, data, rows, cols):
table = self.document.add_table(rows=rows, cols=cols)
header_cells = table.rows[0].cells
header_cells[0].text = 'Qty'
header_cells[1].text = 'Id'
header_cells[2].text = 'Desc'
for qty, id, desc in data:
row_cells = table.add_row().cells
row_cells[0].text = str(qty)
row_cells[1].text = id
row_cells[2].text = desc
def set_cells_border(self, table):
"""给table设置边框"""
for row in range(len(table.rows)):
for col in range(len(table.columns)):
self.set_cell_border(table.cell(row, col),
top={
"sz": 0.5, "val": "single", "color": "#000000", "space": "0"},
bottom={
"sz": 0.5, "val": "single", "color": "#000000", "space": "0"},
left={
"sz": 0.5, "val": "single", "color": "#000000", "space": "0"},
right={
"sz": 0.5, "val": "single", "color": "#000000", "space": "0"},
insideH={
"sz": 0.5, "val": "single", "color": "#000000", "space": "0"},
end={
"sz": 0.5, "val": "single", "color": "#000000", "space": "0"})
def set_cell_border(self, cell, **kwargs):
""" Set cell`s border 设置单个cell的边框 参考文档:http://www.360doc.com/content/22/0204/21/76948455_1015984457.shtml Usage: set_cell_border( cell, top={"sz": 12, "val": "single", "color": "#FF0000", "space": "0"}, bottom={"sz": 12, "color": "#00FF00", "val": "single"}, left={"sz": 24, "val": "dashed", "shadow": "true"}, right={"sz": 12, "val": "dashed"}, ) """
tc = cell._tc
tcPr = tc.get_or_add_tcPr()
# check for tag existnace, if none found, then create one
tcBorders = tcPr.first_child_found_in("w:tcBorders")
if tcBorders is None:
tcBorders = OxmlElement('w:tcBorders')
tcPr.append(tcBorders)
# list over all available tags
for edge in ('left', 'top', 'right', 'bottom', 'insideH', 'insideV'):
edge_data = kwargs.get(edge)
if edge_data:
tag = 'w:{}'.format(edge)
# check for tag existnace, if none found, then create one
element = tcBorders.find(qn(tag))
if element is None:
element = OxmlElement(tag)
tcBorders.append(element)
# looks like order of attributes is important
for key in ["sz", "val", "color", "space", "shadow"]:
if key in edge_data:
element.set(qn('w:{}'.format(key)), str(edge_data[key]))
def magic_doc():
mydoc = MyDoc(project_name=PROJECT_NAME, out_path=f'./{
PROJECT_NAME}_数据库设计.docx')
mydoc.generate_doc()
for label in model_doc_apps:
app = apps.get_app_config(label)
mydoc.add_app_name(app.verbose_name)
for model_name in app.models:
target_cls = apps.get_registered_model(label, model_name)
model_key = target_cls._meta.verbose_name
table_name = target_cls._meta.db_table
fields = dict()
for field in target_cls._meta.fields:
if type(field).__name__ == 'ForeignKey':
f_name = field.name + "_id"
else:
f_name = field.name
if f_name not in fields.keys():
fields[f_name] = dict()
fields[f_name].update(field.__dict__)
fields[f_name]['field_type'] = str(type(field).__name__)
data_list = []
for (k, v) in fields.items():
is_main_key = is_for_key = False
if 'NOT_PROVIDED' in str(v['default']):
v['default'] = ''
if v['choices'] == None:
v['choices'] = ''
if v['primary_key'] is True:
is_main_key = True
if v['field_type'] == 'ForeignKey':
is_for_key = True
key_types = list()
if is_main_key:
key_types.append("主键")
if is_for_key:
key_types.append("外键")
v['primary_key'] = ','.join(key_types)
args = list()
for tag in ['name', 'verbose_name', 'field_type', 'null', 'default', 'primary_key', 'choices']:
if tag == 'choices':
if v[tag]:
args.append(str({
item[0]: item[1] for item in v[tag]}))
else:
args.append("")
elif tag == 'null':
if v[tag]:
args.append(str(v[tag]))
else:
args.append("")
else:
args.append(str(v[tag]))
data_list.append(args)
mydoc.add_model(model_key, table_name, data_list)
mydoc.make_doc()
if __name__ == '__main__':
magic_doc()
边栏推荐
- 深度解析“链动2+1”模式的商业逻辑
- 【云原生】这么火,你不来了解下?
- Jerry's watch pause [chapter]
- gcc编译器包
- 問題——adb shellerror: insufficient permissions for device: verify udev rules.
- 測試入門——集成測試
- Etcd教程 — 第七章 Etcd之事务API
- Different binary search trees [bottom-up backtracking spanning tree + memory search -- space for time]
- Quick sort, query the k-largest number of the sequence
- FortiGate firewall configuration log uploading regularly
猜你喜欢
![Synchronous movement state of Jerry's watch [chapter]](/img/58/a7e73aa32c15ccc7c506d521ca2917.jpg)
Synchronous movement state of Jerry's watch [chapter]

Certification training | streamnational certification training phase 2

图扑软件智慧能源一体化管控平台

leetcode:560. 和为 K 的子数组

2022-2028 global MWIR camera industry research and trend analysis report
![相同的树[从部分到整体]](/img/2d/997b9cb9cd4f8ea8620f5a66fcf00a.png)
相同的树[从部分到整体]

Linear and nonlinear structures

The method of exporting packages of all components from existing PCBs in Altium Designer

For safe login of wechat applet, the openid returned by wechat must be verified first to ensure the uniqueness of information.

初探元宇宙存储,数据存储市场下一个爆点?
随机推荐
[Shangshui Shuo series] the simplest subtitle configuration
广发证券开户是真的安全可靠吗
1110: nearest common ancestor (function topic)
逆序对对数计算,顺序对对数计算——归并排序
問題——adb shellerror: insufficient permissions for device: verify udev rules.
Potential learning C language - pointer explanation (Advanced)
PAT甲级 A1057 Stack
嵌入式开发如何进行源代码保密工作
Setting alarm mode of Jerry's watch [chapter]
priority_ Understanding of queue
2022-2028 global low carbon concrete industry research and trend analysis report
Etcd tutorial - Chapter 6 etcd core API V3
allegro 设计中显示网络飞线或关闭网络飞线的方法
Allegro's method of canceling the routing of a good line
Equal wealth
解决allegro中测量距离时,点击一个点后光标闪烁的问题
Tortoise does not display a green Icon
Getting started with testing - integration testing
There's a mystery behind the little login
归并排序