新增:影响域分析web录入

This commit is contained in:
2026-02-07 17:26:34 +08:00
parent 0bee950a52
commit a76cd8674c
76 changed files with 859 additions and 133 deletions

View File

@@ -15,7 +15,7 @@ from pathlib import Path
from utils.chen_response import ChenResponse
# 导入数据库ORM
from apps.project.models import Project, Contact, Abbreviation, ProjectSoftSummary, StuctSortData, StaticSoftItem, StaticSoftHardware, \
DynamicSoftTable, DynamicHardwareTable
DynamicSoftTable, DynamicHardwareTable, ProjectDynamicDescription, EvaluateData, EnvAnalysis
from apps.dict.models import Dict
# 导入工具函数
from utils.util import get_str_dict, get_list_dict, get_testType, get_ident, get_str_abbr
@@ -290,19 +290,10 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
except PermissionError as e:
return ChenResponse(status=400, code=400, message="模版文件已打开,请关闭后再试,{0}".format(e))
# 生成测评对象 - 包括大纲、说明、回归说明和报告
@route.get('/create/softComposition', url_name='create-softComposition')
@transaction.atomic
def create_softComposition(self, id: int):
# 首先判断是否包含 - 项目信息-软件概述
project_obj = get_object_or_404(Project, id=id)
input_path_2 = Path.cwd() / 'media' / project_path(id) / 'form_template' / 'dg' / '测评对象_2.docx'
doc = DocxTemplate(input_path_2)
soft_summary_qs = ProjectSoftSummary.objects.filter(project=project_obj)
if soft_summary_qs.exists():
data_qs = soft_summary_qs.first().data_schemas
# 生成dataSchemas的context - 服务于 1、测评对象 2、动态环境描述
@classmethod
def create_data_schema_list_context(cls, data_qs, doc: DocxTemplate):
if data_qs.exists():
# 如果存在则渲染此处
data_list = []
for data_obj in data_qs.all():
item_context: dict[str, Any] = {"fontnote": data_obj.fontnote, 'type': data_obj.type}
@@ -344,13 +335,35 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
context = {
"datas": data_list,
}
return context
return None
# 统将需要多个DataSchemas的一对一项目字段生成响应
@classmethod
def uniform_res_from_mul_data_schemas(cls, id: int, filename: str, r_filename: str, model) -> ChenResponse | None:
project_obj = get_object_or_404(Project, id=id)
input_path = Path.cwd() / 'media' / project_path(id) / 'form_template' / 'dg' / filename
doc = DocxTemplate(input_path)
qs = model.objects.filter(project=project_obj)
if qs.exists():
data_qs = qs.first().data_schemas
context = cls.create_data_schema_list_context(data_qs, doc)
doc.render(context)
try:
doc.save(Path.cwd() / "media" / project_path(id) / "output_dir" / '测评对象.docx')
doc.save(Path.cwd() / "media" / project_path(id) / "output_dir" / r_filename)
return ChenResponse(status=200, code=200, message="文档生成成功!")
except PermissionError as e:
return ChenResponse(status=400, code=400, message="模版文件已打开,请关闭后再试,{0}".format(e))
return None
# 生成测评对象 - 包括大纲、说明、回归说明和报告
@route.get('/create/softComposition', url_name='create-softComposition')
@transaction.atomic
def create_softComposition(self, id: int):
# 首先判断是否包含 - 项目信息-软件概述
res = self.uniform_res_from_mul_data_schemas(id, '测评对象_2.docx', '测评对象.docx', ProjectSoftSummary)
if res is not None:
return res
# 原来文档片段或者初始内容
input_path = Path.cwd() / 'media' / project_path(id) / 'form_template' / 'dg' / '测评对象.docx'
doc = DocxTemplate(input_path)
@@ -480,6 +493,8 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
# 处理非第一列
else:
cell.text = table_data[row][col - 1]
# 垂直居中
cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
# 单独处理第一行
for col in range(cols):
cell = table.cell(0, col)
@@ -559,9 +574,14 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
}
return create_dg_docx("静态硬件和固件项.docx", context, id)
# 动态测评环境说明
# 动态测评环境说明 - 多dataSchemas格式
@route.get('/create/dynamic_env', url_name='create-dynamic_env')
def create_dynamic_env(self, id: int):
res = self.uniform_res_from_mul_data_schemas(id, '动态测试环境说明_2.docx',
'动态测试环境说明.docx', ProjectDynamicDescription)
if res is not None:
return res
# 老内容
project_obj: Project = get_object_or_404(Project, id=id)
input_path = Path.cwd() / 'media' / project_path(id) / 'form_template' / 'dg' / '动态测试环境说明.docx'
doc = DocxTemplate(input_path)
@@ -616,6 +636,11 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
# 测试数据
@route.get('/create/test_data', url_name='create-test_data')
def create_test_data(self, id: int):
res = self.uniform_static_dynamic_response(id, '测评数据_2.docx',
'测评数据.docx', EvaluateData)
if res is not None:
return res
# 老内容
input_path = Path.cwd() / 'media' / project_path(id) / 'form_template' / 'dg' / '测评数据.docx'
doc = DocxTemplate(input_path)
replace, frag, rich_text_list = self._generate_frag(id, doc, '测评数据')
@@ -628,6 +653,27 @@ class GenerateControllerDG(ControllerBase, FragementToolsMixin):
# 环境差异性分析
@route.get('/create/env_diff', url_name='create-env_diff')
def create_env_diff(self, id: int):
project_obj: Project = get_object_or_404(Project, id=id)
input_path = Path.cwd() / 'media' / project_path(id) / 'form_template' / 'dg' / '环境差异性分析_2.docx'
doc = DocxTemplate(input_path)
qs = EnvAnalysis.objects.filter(project=project_obj)
if qs.exists():
obj = qs.first()
table_data = obj.table
subdoc = self.create_table_context(table_data, doc)
context = {
"description": obj.description,
"table": subdoc,
"fontnote": obj.fontnote,
}
doc.render(context, autoescape=True)
try:
doc.save(Path.cwd() / "media" / project_path(id) / "output_dir" / '环境差异性分析.docx')
return ChenResponse(status=200, code=200, message="文档生成成功!")
except PermissionError as e:
return ChenResponse(status=400, code=400, message="模版文件已打开,请关闭后再试,{0}".format(e))
# 老内容
input_path = Path.cwd() / 'media' / project_path(id) / 'form_template' / 'dg' / '环境差异性分析.docx'
doc = DocxTemplate(input_path)
replace, frag, rich_text_list = self._generate_frag(id, doc, '环境差异性分析')

View File

@@ -8,7 +8,7 @@ from django.db.models import QuerySet, Q
from docxtpl import DocxTemplate
from docx import Document
# 导入模型
from apps.project.models import Project, Round, Dut
from apps.project.models import Project, Round, Dut, InfluenceArea
from apps.dict.models import Dict
# 导入项目工具
from utils.util import get_list_dict, get_str_dict, get_ident, get_case_ident, get_testType
@@ -19,6 +19,7 @@ from utils.path_utils import project_path
from apps.createDocument.extensions.util import delete_dir_files
from apps.createDocument.extensions.parse_rich_text import RichParser
from apps.createDocument.extensions.documentTime import DocTime
from utils.util import get_str_abbr
# 导入生成日志记录模块
from apps.createSeiTaiDocument.extensions.logger import GenerateLogger
# 导入排序
@@ -235,6 +236,30 @@ class GenerateControllerHSM(ControllerBase):
message=f'您第{chinese_round_name[int(hround.key)]}轮次中缺少源代码版本信息,请添加')
last_dm_version = last_round_so_dut.version
now_dm_version = so_dut.version
# 这里插入影响域分析部分
## 先查找是否有影响域分析填写
area_qs = InfluenceArea.objects.filter(round=hround)
## 如果存在则查询items
if area_qs.exists():
area_obj = area_qs.first()
items_qs = area_obj.influence_items.all()
if items_qs.exists():
# 遍历items
item_render_list = []
for item in items_qs:
# 1.处理关联case - 找第一轮cases
case_str_list = []
for case in project_obj.pcField.filter(key__in=item.effect_cases):
case_ident_index = str(int(case.key.split("-")[-1]) + 1).zfill(3)
case_str_list.append("_".join(["YL", get_str_abbr(case.test.testType, "testType"), case.ident, case_ident_index]))
item_dict = {
"change_type": item.change_type,
"change_influ": item.change_influ,
"case_str_list": case_str_list,
"change_des": item.change_des, # 富文本未处理
}
item_render_list.append(item_dict)
# 如果存在这个轮次的需求文档,则查询上个版本
last_xq_version = ""
if xq_dut:

View File

@@ -396,3 +396,21 @@ class CaseController(ControllerBase):
Case.objects.bulk_update(updated_cases, ['exe_time'])
return ChenResponse(status=200, code=200, data=len(updated_cases),
message=f"成功更新{len(updated_cases)}个用例执行时间")
# 给级联选择器数据 -> 上一轮次所有用例
@route.get("/case/getRelatedCase", url_name='case-related-case')
def get_cases_related_case(self, id: int, round_key: str):
project_obj = get_object_or_404(Project, id=id)
previous_round_obj = project_obj.pField.filter(key=int(round_key) - 1).first()
# dut -> design
data_list = []
for dut in previous_round_obj.rdField.all():
dut_dict = {'label': dut.name, 'value': dut.id, 'children': []}
for design in dut.rsField.all():
design_dict = {'label': design.name, 'value': design.id, 'key': design.key, 'children': []}
for case in design.dcField.all():
case_dict = {'label': case.name, 'value': case.id, 'key': case.key}
design_dict['children'].append(case_dict)
dut_dict['children'].append(design_dict)
data_list.append(dut_dict)
return ChenResponse(message='获取成功', data=data_list)

View File

@@ -15,9 +15,9 @@ from ninja import Query
from utils.chen_response import ChenResponse
from utils.chen_crud import create, multi_delete_project
from apps.project.models import Project, Round, ProjectSoftSummary, StuctSortData, StaticSoftItem, StaticSoftHardware, DynamicSoftTable, \
DynamicHardwareTable
DynamicHardwareTable, ProjectDynamicDescription, EvaluateData, EnvAnalysis
from apps.project.schemas.project import ProjectRetrieveSchema, ProjectFilterSchema, ProjectCreateInput, \
DeleteSchema, SoftSummarySchema, DataSchema, StaticDynamicData
DeleteSchema, SoftSummarySchema, DataSchema, StaticDynamicData, EnvAnalysisSchema
from utils.util import get_str_dict
# 时间处理模块
from apps.project.tool.timeList import time_return_to
@@ -99,6 +99,7 @@ class ProjectController(ControllerBase):
except FileNotFoundError:
return ChenResponse(code=500, status=500, message='文件不存在,请检查')
return ChenResponse(code=200, status=200, message="添加项目成功,并添加第一轮测试")
return ChenResponse(code=400, status=400, message="未添加任何项目")
@route.put("/update/{project_id}")
@transaction.atomic
@@ -139,7 +140,7 @@ class ProjectController(ControllerBase):
project_media_path = media_path / ident
try:
rmtree(project_media_path)
except FileNotFoundError as e:
except FileNotFoundError:
return ChenResponse(status=400, code=400, message='项目模版目录可能不存在,可能之前已删除')
return ChenResponse(message="删除成功!")
@@ -270,48 +271,59 @@ class ProjectController(ControllerBase):
time = time_return_to(id)
return time
# 项目级信息前端告警数据获取
# [变] 项目级信息前端告警数据获取
@route.get("/project_info_status/")
@transaction.atomic
def project_info_status(self, id: int):
# 全部状态
all_status = {
"soft_summary": False,
"interface_image": False,
"static_soft_item": False,
"static_soft_hardware": False,
"dynamic_soft_item": False,
"dynamic_soft_hardware": False,
}
# 1.查看软件概述是否填写
project_obj = self.get_project_by_id(id)
soft_summary_qs = ProjectSoftSummary.objects.filter(project=project_obj)
if soft_summary_qs.exists():
# 存在还要判断是否有子项
if soft_summary_qs.first().data_schemas.exists():
all_status['soft_summary'] = True
# 2.查看接口图是否填写
image_qs = StuctSortData.objects.filter(project=project_obj)
if image_qs.exists():
all_status['interface_image'] = True
# 3.查看静态软件项是否填写
static_item_qs = StaticSoftItem.objects.filter(project=project_obj)
if static_item_qs.exists():
all_status['static_soft_item'] = True
# 4.静态硬件项
static_hardware_qs = StaticSoftHardware.objects.filter(project=project_obj)
if static_hardware_qs.exists():
all_status['static_soft_hardware'] = True
# 5.动态软件项
dynamic_soft_item_qs = DynamicSoftTable.objects.filter(project=project_obj)
if dynamic_soft_item_qs.exists():
all_status['dynamic_soft_item'] = True
# 5.动态软件项
dynamic_hardware_qs = DynamicHardwareTable.objects.filter(project=project_obj)
if dynamic_hardware_qs.exists():
all_status['dynamic_soft_hardware'] = True
# 统一配置每个状态的检查逻辑
status_configs = {
"soft_summary": {
"model": ProjectSoftSummary,
"check": lambda qs: qs.exists() and qs.first().data_schemas.exists()
},
"interface_image": {
"model": StuctSortData,
"check": lambda qs: qs.exists()
},
"static_soft_item": {
"model": StaticSoftItem,
"check": lambda qs: qs.exists()
},
"static_soft_hardware": {
"model": StaticSoftHardware,
"check": lambda qs: qs.exists()
},
"dynamic_soft_item": {
"model": DynamicSoftTable,
"check": lambda qs: qs.exists()
},
"dynamic_soft_hardware": {
"model": DynamicHardwareTable,
"check": lambda qs: qs.exists()
},
"dynamic_des": {
"model": ProjectDynamicDescription,
"check": lambda qs: qs.exists() and qs.first().data_schemas.exists()
},
"evaluate_data": {
"model": EvaluateData,
"check": lambda qs: qs.exists()
},
"env_analysis": {
"model": EnvAnalysis,
"check": lambda qs: qs.exists()
}
}
all_status = {}
for status_key, config in status_configs.items():
qs = config["model"].objects.filter(project=project_obj)
all_status[status_key] = config["check"](qs)
return ChenResponse(status=200, code=20000, data=all_status, message='查询成功')
# [变] 封装结构化数据新增-修改针对project - OneToOne - DataSchemas形式
@classmethod
def bulk_create_data_schemas(cls, parent_obj, datas: list[DataSchema]):
"""
@@ -321,11 +333,13 @@ class ProjectController(ControllerBase):
datas (list[DataSchema]): 数据模式对象列表
"""
# 动态确定所属父model
field_name = None
field_name = None # type:ignore
if isinstance(parent_obj, ProjectSoftSummary):
field_name = 'soft_summary'
elif isinstance(parent_obj, Project):
field_name = 'project'
elif isinstance(parent_obj, ProjectDynamicDescription):
field_name = 'dynamic_description'
else:
raise HttpError(400, "添加的数据未在系统内,请联系管理员")
@@ -340,39 +354,66 @@ class ProjectController(ControllerBase):
data_list.append(new_data)
StuctSortData.objects.bulk_create(data_list)
# 封装只有model不同 -修改和新增dataSchemas针对project - OneToOne - DataSchemas形式
@classmethod
def create_or_modify_data_schemas(cls, id: int, model, data):
project_obj = get_object_or_404(Project, pk=id)
qs = model.objects.filter(project=project_obj)
if qs.exists():
obj = qs.first()
# 如果存在则修改:先删除再创建
obj.data_schemas.all().delete()
cls.bulk_create_data_schemas(obj, data)
else:
parent_obj = model.objects.create(project=project_obj)
cls.bulk_create_data_schemas(parent_obj, data)
# ~~~软件概述-新增和修改~~~
@route.post('/soft_summary/')
@transaction.atomic
def soft_summary(self, payload: SoftSummarySchema):
project_obj = self.get_project_by_id(payload.id)
# 安全获取-软件概述
soft_summary_qs = ProjectSoftSummary.objects.filter(project=project_obj)
if soft_summary_qs.exists():
soft_summary = soft_summary_qs.first()
# 如果存在则修改:先删除然后创建
soft_summary.data_schemas.all().delete()
self.bulk_create_data_schemas(soft_summary, payload.data)
else:
# 不存在软件概述则创建
soft_summary_obj = ProjectSoftSummary.objects.create(project=project_obj)
self.bulk_create_data_schemas(soft_summary_obj, payload.data)
self.create_or_modify_data_schemas(payload.id, ProjectSoftSummary, payload.data)
# ~~~动态环境描述-新增和修改~~~
@route.post('/dynamic_description/')
@transaction.atomic
def dynamic_description(self, payload: SoftSummarySchema):
self.create_or_modify_data_schemas(payload.id, ProjectDynamicDescription, payload.data)
@classmethod
def get_res_from_info(cls, project_obj: Project, model) -> list[dict] | None:
"""model: 当前一对一模型,直接获取结构化数据信息数组返回"""
qs = model.objects.filter(project=project_obj)
if qs.exists():
obj = qs.first()
ds_qs = obj.data_schemas.all()
data_list = [{
"type": item.type,
"content": item.content,
"fontnote": item.fontnote,
} for item in ds_qs]
return data_list
return None
# ~~~软件概述-获取到前端展示~~~
@route.get("/get_soft_summary/", response=list[DataSchema])
@transaction.atomic
def get_soft_summary(self, id: int):
project_obj = self.get_project_by_id(id)
soft_summary_qs = ProjectSoftSummary.objects.filter(project=project_obj)
if soft_summary_qs.exists():
# 如果存在则返回数据
soft_summary = soft_summary_qs.first()
dataSchem_qs = soft_summary.data_schemas.all()
return ChenResponse(status=200, code=25001, data=[{
"type": item.type,
"content": item.content,
"fontnote": item.fontnote,
} for item in dataSchem_qs])
return ChenResponse(status=200, code=25002, data=[])
data_list = self.get_res_from_info(project_obj, ProjectSoftSummary)
if data_list:
return ChenResponse(status=200, code=20000, data=data_list)
return ChenResponse(status=200, code=20000, data=[])
# ~~~动态环境描述 - 获取展示~~~
@route.get("/dynamic_des/", response=list[DataSchema])
@transaction.atomic
def get_dynamic_des(self, id: int):
project_obj = self.get_project_by_id(id)
data_list = self.get_res_from_info(project_obj, ProjectDynamicDescription)
if data_list:
return ChenResponse(status=200, code=20000, data=data_list)
return ChenResponse(status=200, code=20000, data=[])
# ~~~接口图新增或修改~~~
@route.post("/interface_image/")
@@ -400,13 +441,15 @@ class ProjectController(ControllerBase):
})
return ChenResponse(status=200, code=25002, data=None)
# 动态返回是哪个模型
@classmethod
def get_model_from_category(cls, category: str):
mapDict = {
'静态软件项': StaticSoftItem,
'静态硬件项': StaticSoftHardware,
'动态软件项': DynamicSoftTable,
'动态硬件项': DynamicHardwareTable
'动态硬件项': DynamicHardwareTable,
'测评数据': EvaluateData
}
return mapDict[category]
@@ -424,7 +467,6 @@ class ProjectController(ControllerBase):
@route.post("/post_static_dynamic_item/")
@transaction.atomic
def post_static_dynamic_item(self, data: StaticDynamicData):
print(data)
project_obj = self.get_project_by_id(data.id)
model = self.get_model_from_category(data.category)
item_qs = model.objects.filter(project=project_obj)
@@ -432,3 +474,24 @@ class ProjectController(ControllerBase):
# 如果存在则修改
item_qs.delete()
model.objects.create(project=project_obj, table=data.table, fontnote=data.fontnote)
# ~~~环境差异性分析 - 获取~~~
@route.get("/get_env_analysis/")
@transaction.atomic
def get_env_analysis(self, id: int):
project_obj = self.get_project_by_id(id)
qs = EnvAnalysis.objects.filter(project=project_obj)
if qs.exists():
obj = qs.first()
return ChenResponse(status=200, code=25001, data={"table": obj.table, "fontnote": obj.fontnote, "description": obj.description})
return ChenResponse(status=200, code=25002, data=None)
# ~~~环境差异性分析 - 新增和修改~~~
@route.post("/post_env_analysis/")
@transaction.atomic
def post_env_analysis(self, data: EnvAnalysisSchema):
project_obj = self.get_project_by_id(data.id)
qs = EnvAnalysis.objects.filter(project=project_obj)
if qs.exists():
qs.delete()
EnvAnalysis.objects.create(project=project_obj, table=data.table, fontnote=data.fontnote, description=data.description)

View File

@@ -2,9 +2,9 @@ from ninja_extra import api_controller, ControllerBase, route
from ninja_jwt.authentication import JWTAuth
from ninja_extra.permissions import IsAuthenticated
from django.db import transaction
from apps.project.models import Round
from apps.project.models import Round, InfluenceArea, InfluenceItem
from apps.project.schemas.round import TreeReturnRound, RoundInfoOutSchema, EditSchemaIn, DeleteSchema, \
CreateRoundOutSchema, CreateRoundInputSchema
CreateRoundOutSchema, CreateRoundInputSchema, InfluenceItemOutSchema, InfluenceInputSchema
from typing import List
from utils.chen_response import ChenResponse
from apps.project.tools.delete_change_key import round_delete_sub_node_key
@@ -81,3 +81,63 @@ class RoundController(ControllerBase):
return ChenResponse(code=400, status=400, message='标识和其他重复')
Round.objects.create(**asert_dict)
return ChenResponse(message="新增轮次成功")
# ~~~影响域分析 - 获取数据和状态~~~
@route.get("/round/get_influence", response=List[InfluenceItemOutSchema], url_name="round-get-influence-items")
@transaction.atomic
def get_influence(self, id: int, round_key: str):
round_qs = Round.objects.filter(project__id=id, key=round_key)
round_obj = round_qs.first()
influence_qs = InfluenceArea.objects.filter(round=round_obj)
if influence_qs.exists():
influence = influence_qs.first()
items_qs = influence.influence_items.all()
if items_qs.exists():
return items_qs
return ChenResponse(status=200, code=25002, data=[])
# ~~~影响域分析是否有值~~~
@route.get("/round/get_status_influence", url_name="round-get-status-influence")
@transaction.atomic
def get_status_influence(self, id: int, round_key: str):
round_qs = Round.objects.filter(project__id=id, key=round_key)
round_obj = round_qs.first()
influence_qs = InfluenceArea.objects.filter(round=round_obj)
if influence_qs.exists():
influence = influence_qs.first()
items_qs = influence.influence_items.all()
if items_qs.exists():
return ChenResponse(status=200, code=25005, data=True)
return ChenResponse(status=200, code=25006, data=False)
# ~~~影响域分析 - 修改或新增~~~
@route.post("/round/create_influence", url_name="round-influence-create")
@transaction.atomic
def post_influence(self, data: InfluenceInputSchema):
print(data)
round_obj = Round.objects.filter(project_id=data.id, key=data.round_key).first()
influence_area_qs = InfluenceArea.objects.filter(round=round_obj)
if influence_area_qs.exists():
influence_area_obj = influence_area_qs.first()
influence_area_obj.influence_items.all().delete()
# 先删除再创建
data_list = []
for item in data.item_list:
new_item = InfluenceItem(influence=influence_area_obj,
change_type=item.change_type,
change_influ=item.change_influ,
change_des=item.change_des,
effect_cases=item.effect_cases)
data_list.append(new_item)
InfluenceItem.objects.bulk_create(data_list)
else:
parent_obj = InfluenceArea.objects.create(round=round_obj)
data_list = []
for item in data.item_list:
new_item = InfluenceItem(influence=parent_obj,
change_type=item.change_type,
change_influ=item.change_influ,
change_des=item.change_des,
effect_cases=item.effect_cases)
data_list.append(new_item)
InfluenceItem.objects.bulk_create(data_list)

View File

@@ -0,0 +1,28 @@
# Generated by Django 6.0.2 on 2026-02-06 10:56
import apps.project.models
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('project', '0024_projectdynamicdescription_and_more'),
]
operations = [
migrations.CreateModel(
name='EvaluateData',
fields=[
('project', models.OneToOneField(db_constraint=False, help_text='关联项目', on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='evaluate_data', serialize=False, to='project.project', verbose_name='关联项目')),
('table', models.JSONField(default=apps.project.models.default_json_value, help_text='储存表格二维数组', verbose_name='储存表格二维数组')),
('fontnote', models.CharField(default='', help_text='数据的题注说明', max_length=256, null=True, verbose_name='题注')),
],
options={
'verbose_name': '测评数据',
'verbose_name_plural': '测评数据',
'db_table': 'project_evaluate_data',
},
),
]

View File

@@ -0,0 +1,29 @@
# Generated by Django 6.0.2 on 2026-02-06 13:56
import apps.project.models
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('project', '0025_evaluatedata'),
]
operations = [
migrations.CreateModel(
name='EnvAnalysis',
fields=[
('project', models.OneToOneField(db_constraint=False, help_text='关联项目', on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='env_analysis', serialize=False, to='project.project', verbose_name='关联项目')),
('table', models.JSONField(default=apps.project.models.default_json_value, help_text='储存表格二维数组', verbose_name='储存表格二维数组')),
('fontnote', models.CharField(default='', help_text='数据的题注说明', max_length=256, null=True, verbose_name='题注')),
('description', models.CharField(default='', max_length=1024, null=True, verbose_name='差异性分析文字')),
],
options={
'verbose_name': '环境差异性分析表',
'verbose_name_plural': '环境差异性分析表',
'db_table': 'project_env_analysis',
},
),
]

View File

@@ -0,0 +1,46 @@
# Generated by Django 6.0.2 on 2026-02-06 16:05
import apps.project.models
import django.db.models.deletion
import tinymce.models
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('project', '0026_envanalysis'),
]
operations = [
migrations.CreateModel(
name='InfluenceArea',
fields=[
('project', models.OneToOneField(db_constraint=False, help_text='关联项目', on_delete=django.db.models.deletion.CASCADE, primary_key=True, related_name='influence', serialize=False, to='project.round', verbose_name='关联项目')),
],
options={
'verbose_name': '影响域分析',
'verbose_name_plural': '影响域分析',
'db_table': 'round_influence_area',
},
),
migrations.CreateModel(
name='InfluenceItem',
fields=[
('id', models.BigAutoField(help_text='Id', primary_key=True, serialize=False, verbose_name='Id')),
('remark', models.CharField(blank=True, help_text='描述', max_length=255, null=True, verbose_name='描述')),
('update_datetime', models.DateField(auto_now=True, help_text='修改时间', null=True, verbose_name='修改时间')),
('create_datetime', models.DateField(auto_now_add=True, help_text='创建时间', null=True, verbose_name='创建时间')),
('sort', models.IntegerField(blank=True, default=1, help_text='显示排序', null=True, verbose_name='显示排序')),
('change_type', models.CharField(default='', help_text='更改类型', max_length=256, null=True, verbose_name='更改类型')),
('change_des', tinymce.models.HTMLField(blank=True, null=True, verbose_name='更改内容描述')),
('effect_cases', models.JSONField(default=apps.project.models.create_list, verbose_name='影响的用例key数组')),
('influence', models.ForeignKey(blank=True, db_constraint=False, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='influence_items', to='project.influencearea', verbose_name='所属影响域分析')),
],
options={
'verbose_name': '影响域分析 - 行数据',
'verbose_name_plural': '影响域分析 - 行数据',
'db_table': 'influence_item',
},
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 6.0.2 on 2026-02-07 13:45
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('project', '0027_influencearea_influenceitem'),
]
operations = [
migrations.RenameField(
model_name='influencearea',
old_name='project',
new_name='round',
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 6.0.2 on 2026-02-07 16:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('project', '0028_rename_project_influencearea_round'),
]
operations = [
migrations.AddField(
model_name='influenceitem',
name='change_influ',
field=models.TextField(default='', help_text='影响域分析', max_length=2048, null=True, verbose_name='影响域分析'),
),
]

View File

@@ -542,7 +542,6 @@ class DynamicSoftTable(models.Model):
class DynamicHardwareTable(models.Model):
project = models.OneToOneField(to="Project", primary_key=True, db_constraint=False, related_name="dynamic_hardware", on_delete=models.CASCADE,
verbose_name="关联项目", help_text="关联项目")
table = models.JSONField(verbose_name="储存表格二维数组", help_text="储存表格二维数组", default=default_json_value)
fontnote = models.CharField(max_length=256, null=True, default="", verbose_name="题注", help_text="数据的题注说明")
@@ -551,6 +550,32 @@ class DynamicHardwareTable(models.Model):
verbose_name = "动态硬件项表"
verbose_name_plural = verbose_name
# 一对一项目model动态环境 - 测评数据
class EvaluateData(models.Model):
project = models.OneToOneField(to="Project", primary_key=True, db_constraint=False, related_name="evaluate_data", on_delete=models.CASCADE,
verbose_name="关联项目", help_text="关联项目")
table = models.JSONField(verbose_name="储存表格二维数组", help_text="储存表格二维数组", default=default_json_value)
fontnote = models.CharField(max_length=256, null=True, default="", verbose_name="题注", help_text="数据的题注说明")
class Meta:
db_table = 'project_evaluate_data'
verbose_name = "测评数据"
verbose_name_plural = verbose_name
# 一对一项目model环境差异性分析
class EnvAnalysis(models.Model):
project = models.OneToOneField(to="Project", primary_key=True, db_constraint=False,
related_name="env_analysis", on_delete=models.CASCADE,
verbose_name="关联项目", help_text="关联项目")
table = models.JSONField(verbose_name="储存表格二维数组", help_text="储存表格二维数组", default=default_json_value)
fontnote = models.CharField(max_length=256, null=True, default="", verbose_name="题注", help_text="数据的题注说明")
description = models.CharField(max_length=1024, null=True, default="", verbose_name="差异性分析文字")
class Meta:
db_table = 'project_env_analysis'
verbose_name = "环境差异性分析表"
verbose_name_plural = verbose_name
# 结构化排序数据
class StuctSortData(CoreModel):
"""
@@ -582,11 +607,7 @@ class StuctSortData(CoreModel):
help_text="数据的题注说明"
)
# 内容字段 - 存储字符串、列表、字典
content = models.JSONField(
verbose_name="内容",
help_text="存储文本内容或二维表格数据或图片数据",
default=default_json_value
)
content = models.JSONField(verbose_name="内容", help_text="存储文本内容或二维表格数据或图片数据", default=default_json_value)
class Meta:
db_table = 'data_schemas'
@@ -595,3 +616,28 @@ class StuctSortData(CoreModel):
def __str__(self):
return f"结构排序化数据:({self.pk})"
# 影响域分析 - 隶属:轮次(不能是第一轮次)
class InfluenceArea(models.Model):
round = models.OneToOneField(to="Round", primary_key=True, db_constraint=False,
related_name="influence", on_delete=models.CASCADE,
verbose_name="关联项目", help_text="关联项目")
class Meta:
db_table = 'round_influence_area'
verbose_name = "影响域分析"
verbose_name_plural = verbose_name
class InfluenceItem(CoreModel):
# 外键:影响域分析
influence = models.ForeignKey(InfluenceArea, db_constraint=False, related_name="influence_items", verbose_name="所属影响域分析",
on_delete=models.CASCADE, null=True, blank=True)
change_type = models.CharField(max_length=256, null=True, default="", verbose_name="更改类型", help_text="更改类型")
change_influ = models.TextField(max_length=2048, null=True, default="", verbose_name="影响域分析", help_text="影响域分析")
change_des = HTMLField(blank=True, null=True, verbose_name="更改内容描述")
effect_cases = models.JSONField(default=create_list, verbose_name="影响的用例key数组")
class Meta:
db_table = 'influence_item'
verbose_name = "影响域分析 - 行数据"
verbose_name_plural = verbose_name

View File

@@ -62,3 +62,10 @@ class StaticDynamicData(Schema):
category: str
table: list[list[str]]
fontnote: Optional[str] = ""
# ~~~环境差异性分析~~~
class EnvAnalysisSchema(Schema):
id: int
table: list[list[str]]
fontnote: Optional[str] = ""
description: Optional[str] = ""

View File

@@ -1,7 +1,7 @@
from typing import Optional
from ninja import Schema, ModelSchema
from pydantic import Field
from apps.project.models import Round
from apps.project.models import Round, InfluenceItem
# 输出树状信息的schema
class TreeReturnRound(Schema):
@@ -55,3 +55,21 @@ class CreateRoundInputSchema(ModelSchema):
fields_optional = ['best_condition_tem', 'best_condition_voltage',
'low_condition_tem', 'low_condition_voltage', 'typical_condition_tem',
'typical_condition_voltage' 'grade']
# influence_item return
class InfluenceItemOutSchema(ModelSchema):
class Meta:
model = InfluenceItem
fields = ['id', 'change_type', 'change_des', 'effect_cases', 'change_influ']
# influence input
class OneItemInputSchema(Schema):
change_type: str
change_des: Optional[str] = ""
effect_cases: Optional[list[str]] = []
change_influ: Optional[str] = ""
class InfluenceInputSchema(Schema):
id: int
round_key: str
item_list: list[OneItemInputSchema]

View File

@@ -292,3 +292,307 @@ FileNotFoundError: [Errno 2] No such file or directory: 'E:\\pycharmProjects\\cd
[WARNING][2026-02-05 18:19:31,559][log.py:249]Unprocessable Content: /api/testmanage/project/soft_summary/
[WARNING][2026-02-05 18:20:01,886][operation.py:131]"POST - ProjectController[soft_summary] /api/testmanage/project/soft_summary/" ([{'type': 'missing', 'loc': ('body', 'payload', 'id'), 'msg': 'Field required'}, {'type': 'missing', 'loc': ('body', 'payload', 'data'), 'msg': 'Field required'}],)
[WARNING][2026-02-05 18:20:01,896][log.py:249]Unprocessable Content: /api/testmanage/project/soft_summary/
[WARNING][2026-02-06 09:19:08,011][log.py:249]Unauthorized: /api/system/getInfo
[WARNING][2026-02-06 09:19:08,068][log.py:249]Unauthorized: /api/system/logout
[WARNING][2026-02-06 09:19:17,445][backend.py:91]Caught LDAPError looking up user: SERVER_DOWN({'result': -1, 'desc': "Can't contact LDAP server", 'ctrls': []})
[WARNING][2026-02-06 09:32:51,032][log.py:249]Not Found: /api/testmanage/project/dynamic_des/
[WARNING][2026-02-06 09:32:57,510][log.py:249]Not Found: /api/testmanage/project/dynamic_des/
[WARNING][2026-02-06 09:33:05,303][log.py:249]Method Not Allowed: /api/testmanage/project/dynamic_des/
[WARNING][2026-02-06 10:01:55,025][operation.py:131]"POST - ProjectController[dynamic_description] /api/testmanage/project/dynamic_description/" (400, '添加的数据未在系统内,请联系管理员')
[WARNING][2026-02-06 10:01:55,034][log.py:249]Bad Request: /api/testmanage/project/dynamic_description/
[WARNING][2026-02-06 10:02:03,145][operation.py:131]"POST - ProjectController[dynamic_description] /api/testmanage/project/dynamic_description/" (400, '添加的数据未在系统内,请联系管理员')
[WARNING][2026-02-06 10:02:03,155][log.py:249]Bad Request: /api/testmanage/project/dynamic_description/
[WARNING][2026-02-06 10:02:43,130][operation.py:131]"POST - ProjectController[dynamic_description] /api/testmanage/project/dynamic_description/" (400, '添加的数据未在系统内,请联系管理员')
[WARNING][2026-02-06 10:02:43,141][log.py:249]Bad Request: /api/testmanage/project/dynamic_description/
[WARNING][2026-02-06 10:39:53,890][operation.py:131]"GET - GenerateControllerDG[create_dynamic_env] /api/generate/create/dynamic_env" ("expected token 'end of statement block', got 'table'",)
[ERROR][2026-02-06 10:39:53,891][errors.py:131]expected token 'end of statement block', got 'table'
Traceback (most recent call last):
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run
result = self.view_func(request, **ctx.kwargs["view_func_kwargs"])
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view
result = self.route.view_func(
ctx.controller_instance, *args, **ctx.view_func_kwargs
)
File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 578, in create_dynamic_env
res = self.uniform_res_from_mul_data_schemas(id, '动态测试环境说明_2.docx',
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'动态测试环境说明.docx', ProjectDynamicDescription)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 351, in uniform_res_from_mul_data_schemas
doc.render(context)
~~~~~~~~~~^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 489, in render
xml_src = self.build_xml(context, jinja_env)
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 436, in build_xml
xml = self.render_xml_part(xml, self.docx._part, context, jinja_env)
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 322, in render_xml_part
raise exc
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 312, in render_xml_part
template = Template(src_xml)
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 1214, in __new__
return env.from_string(source, template_class=cls)
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 1111, in from_string
return cls.from_code(self, self.compile(source), gs, None)
~~~~~~~~~~~~^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 771, in compile
self.handle_exception(source=source_hint)
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 942, in handle_exception
raise rewrite_traceback_stack(source=source)
File "<unknown>", line 4, in template
jinja2.exceptions.TemplateSyntaxError: expected token 'end of statement block', got 'table'
[ERROR][2026-02-06 10:39:53,923][log.py:249]Internal Server Error: /api/generate/create/dynamic_env
[WARNING][2026-02-06 10:40:33,124][operation.py:131]"GET - GenerateControllerDG[create_dynamic_env] /api/generate/create/dynamic_env" ('unexpected char "\'" at 5156',)
[ERROR][2026-02-06 10:40:33,127][errors.py:131]unexpected char "'" at 5156
Traceback (most recent call last):
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run
result = self.view_func(request, **ctx.kwargs["view_func_kwargs"])
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view
result = self.route.view_func(
ctx.controller_instance, *args, **ctx.view_func_kwargs
)
File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 578, in create_dynamic_env
res = self.uniform_res_from_mul_data_schemas(id, '动态测试环境说明_2.docx',
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
'动态测试环境说明.docx', ProjectDynamicDescription)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\apps\createDocument\controllers\dg.py", line 351, in uniform_res_from_mul_data_schemas
doc.render(context)
~~~~~~~~~~^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 489, in render
xml_src = self.build_xml(context, jinja_env)
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 436, in build_xml
xml = self.render_xml_part(xml, self.docx._part, context, jinja_env)
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 322, in render_xml_part
raise exc
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\docxtpl\template.py", line 312, in render_xml_part
template = Template(src_xml)
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 1214, in __new__
return env.from_string(source, template_class=cls)
~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 1111, in from_string
return cls.from_code(self, self.compile(source), gs, None)
~~~~~~~~~~~~^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 771, in compile
self.handle_exception(source=source_hint)
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\jinja2\environment.py", line 942, in handle_exception
raise rewrite_traceback_stack(source=source)
File "<unknown>", line 4, in template
jinja2.exceptions.TemplateSyntaxError: unexpected char "'" at 5156
[ERROR][2026-02-06 10:40:33,143][log.py:249]Internal Server Error: /api/generate/create/dynamic_env
[WARNING][2026-02-06 10:52:55,927][operation.py:131]"GET - ProjectController[get_static_dynamic_items] /api/testmanage/project/get_static_dynamic_items/" ('测评数据',)
[ERROR][2026-02-06 10:52:55,927][errors.py:131]'测评数据'
Traceback (most recent call last):
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run
result = self.view_func(request, **ctx.kwargs["view_func_kwargs"])
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view
result = self.route.view_func(
ctx.controller_instance, *args, **ctx.view_func_kwargs
)
File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\project.py", line 454, in get_static_dynamic_items
item_qs = self.get_model_from_category(category).objects.filter(project=project_obj)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\project.py", line 448, in get_model_from_category
return mapDict[category]
~~~~~~~^^^^^^^^^^
KeyError: '测评数据'
[ERROR][2026-02-06 10:52:55,929][log.py:249]Internal Server Error: /api/testmanage/project/get_static_dynamic_items/
[WARNING][2026-02-06 13:56:16,158][operation.py:131]"GET - ProjectController[get_env_analysis] /api/testmanage/project/get_env_analysis/" (1146, "Table 'chengdu_test_plant_v1.project_env_analysis' doesn't exist")
[ERROR][2026-02-06 13:56:16,158][errors.py:131](1146, "Table 'chengdu_test_plant_v1.project_env_analysis' doesn't exist")
Traceback (most recent call last):
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\utils.py", line 105, in _execute
return self.cursor.execute(sql, params)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\mysql\base.py", line 78, in execute
return self.cursor.execute(query, args)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\MySQLdb\cursors.py", line 179, in execute
res = self._query(mogrified_query)
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\MySQLdb\cursors.py", line 330, in _query
db.query(q)
~~~~~~~~^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\MySQLdb\connections.py", line 280, in query
_mysql.connection.query(self, query)
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
MySQLdb.ProgrammingError: (1146, "Table 'chengdu_test_plant_v1.project_env_analysis' doesn't exist")
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run
result = self.view_func(request, **ctx.kwargs["view_func_kwargs"])
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view
result = self.route.view_func(
ctx.controller_instance, *args, **ctx.view_func_kwargs
)
File "D:\programs\uv\python\cpython-3.13.11-windows-x86_64-none\Lib\contextlib.py", line 85, in inner
return func(*args, **kwds)
File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\project.py", line 485, in get_env_analysis
if qs.exists():
~~~~~~~~~^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\query.py", line 1337, in exists
return self.query.has_results(using=self.db)
~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\sql\query.py", line 686, in has_results
return compiler.has_results()
~~~~~~~~~~~~~~~~~~~~^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\sql\compiler.py", line 1592, in has_results
return bool(self.execute_sql(SINGLE))
~~~~~~~~~~~~~~~~^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\sql\compiler.py", line 1624, in execute_sql
cursor.execute(sql, params)
~~~~~~~~~~~~~~^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\utils.py", line 122, in execute
return super().execute(sql, params)
~~~~~~~~~~~~~~~^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\utils.py", line 79, in execute
return self._execute_with_wrappers(
~~~~~~~~~~~~~~~~~~~~~~~~~~~^
sql, params, many=False, executor=self._execute
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
)
^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\utils.py", line 92, in _execute_with_wrappers
return executor(sql, params, many, context)
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\utils.py", line 100, in _execute
with self.db.wrap_database_errors:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\utils.py", line 94, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\utils.py", line 105, in _execute
return self.cursor.execute(sql, params)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\backends\mysql\base.py", line 78, in execute
return self.cursor.execute(query, args)
~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\MySQLdb\cursors.py", line 179, in execute
res = self._query(mogrified_query)
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\MySQLdb\cursors.py", line 330, in _query
db.query(q)
~~~~~~~~^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\MySQLdb\connections.py", line 280, in query
_mysql.connection.query(self, query)
~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^
django.db.utils.ProgrammingError: (1146, "Table 'chengdu_test_plant_v1.project_env_analysis' doesn't exist")
[ERROR][2026-02-06 13:56:16,179][log.py:249]Internal Server Error: /api/testmanage/project/get_env_analysis/
[WARNING][2026-02-06 14:05:16,384][operation.py:131]"GET - ProjectController[get_env_analysis] /api/testmanage/project/get_env_analysis/" ([{'type': 'missing', 'loc': ('query', 'id'), 'msg': 'Field required'}],)
[WARNING][2026-02-06 14:05:16,392][log.py:249]Unprocessable Content: /api/testmanage/project/get_env_analysis/
[WARNING][2026-02-06 14:05:45,945][operation.py:131]"GET - ProjectController[get_env_analysis] /api/testmanage/project/get_env_analysis/" ([{'type': 'missing', 'loc': ('query', 'id'), 'msg': 'Field required'}],)
[WARNING][2026-02-06 14:05:45,955][log.py:249]Unprocessable Content: /api/testmanage/project/get_env_analysis/
[WARNING][2026-02-06 14:07:06,442][log.py:249]Method Not Allowed: /api/testmanage/project/post_env_analysis/
[WARNING][2026-02-06 17:54:26,693][log.py:249]Not Found: /api/project/case/getRelatedCase/
[WARNING][2026-02-06 17:55:19,893][log.py:249]Not Found: /api/project/case/getRelatedCase/
[WARNING][2026-02-06 17:55:54,935][log.py:249]Not Found: /api/project/case/getRelatedCase/
[WARNING][2026-02-06 17:55:57,677][log.py:249]Not Found: /api/project/case/getRelatedCase/
[WARNING][2026-02-06 17:56:36,885][log.py:249]Not Found: /api/project/case/getRelatedCase/
[WARNING][2026-02-06 17:56:39,905][log.py:249]Not Found: /api/project/case/getRelatedCase/
[WARNING][2026-02-07 12:50:41,012][log.py:249]Unauthorized: /api/system/getInfo
[WARNING][2026-02-07 12:50:41,075][log.py:249]Unauthorized: /api/system/logout
[WARNING][2026-02-07 12:50:44,998][backend.py:91]Caught LDAPError looking up user: SERVER_DOWN({'result': -1, 'desc': "Can't contact LDAP server", 'ctrls': []})
[WARNING][2026-02-07 13:37:04,069][operation.py:131]"GET - RoundController[get_influence] /api/project/round/get_influence" ("'QuerySet' object has no attribute 'influence'",)
[ERROR][2026-02-07 13:37:04,069][errors.py:131]'QuerySet' object has no attribute 'influence'
Traceback (most recent call last):
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run
result = self.view_func(request, **ctx.kwargs["view_func_kwargs"])
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view
result = self.route.view_func(
ctx.controller_instance, *args, **ctx.view_func_kwargs
)
File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\round.py", line 89, in get_influence
influence_qs = round_qs.influence.all()
^^^^^^^^^^^^^^^^^^
AttributeError: 'QuerySet' object has no attribute 'influence'
[ERROR][2026-02-07 13:37:04,071][log.py:249]Internal Server Error: /api/project/round/get_influence
[WARNING][2026-02-07 13:37:39,505][operation.py:131]"GET - RoundController[get_influence] /api/project/round/get_influence" ('Round has no influence.',)
[ERROR][2026-02-07 13:37:39,505][errors.py:131]Round has no influence.
Traceback (most recent call last):
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run
result = self.view_func(request, **ctx.kwargs["view_func_kwargs"])
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view
result = self.route.view_func(
ctx.controller_instance, *args, **ctx.view_func_kwargs
)
File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\round.py", line 89, in get_influence
influence_qs = round_qs.first().influence.all()
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\fields\related_descriptors.py", line 520, in __get__
raise self.RelatedObjectDoesNotExist(
...<2 lines>...
)
apps.project.models.Round.influence.RelatedObjectDoesNotExist: Round has no influence.
[ERROR][2026-02-07 13:37:39,508][log.py:249]Internal Server Error: /api/project/round/get_influence
[WARNING][2026-02-07 13:38:15,267][operation.py:131]"GET - RoundController[get_influence] /api/project/round/get_influence" ('Round has no influence.',)
[ERROR][2026-02-07 13:38:15,267][errors.py:131]Round has no influence.
Traceback (most recent call last):
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run
result = self.view_func(request, **ctx.kwargs["view_func_kwargs"])
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view
result = self.route.view_func(
ctx.controller_instance, *args, **ctx.view_func_kwargs
)
File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\round.py", line 89, in get_influence
influence_qs = round_qs.first().influence.all()
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\fields\related_descriptors.py", line 520, in __get__
raise self.RelatedObjectDoesNotExist(
...<2 lines>...
)
apps.project.models.Round.influence.RelatedObjectDoesNotExist: Round has no influence.
[ERROR][2026-02-07 13:38:15,269][log.py:249]Internal Server Error: /api/project/round/get_influence
[WARNING][2026-02-07 13:39:10,565][operation.py:131]"GET - RoundController[get_influence] /api/project/round/get_influence" ('Round has no influence.',)
[ERROR][2026-02-07 13:39:10,565][errors.py:131]Round has no influence.
Traceback (most recent call last):
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run
result = self.view_func(request, **ctx.kwargs["view_func_kwargs"])
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view
result = self.route.view_func(
ctx.controller_instance, *args, **ctx.view_func_kwargs
)
File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\round.py", line 89, in get_influence
influence_qs = round_qs.first().influence.all()
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\fields\related_descriptors.py", line 520, in __get__
raise self.RelatedObjectDoesNotExist(
...<2 lines>...
)
apps.project.models.Round.influence.RelatedObjectDoesNotExist: Round has no influence.
[ERROR][2026-02-07 13:39:10,568][log.py:249]Internal Server Error: /api/project/round/get_influence
[WARNING][2026-02-07 14:25:27,963][operation.py:131]"POST - RoundController[post_influence] /api/project/round/create_influence" ([{'type': 'missing', 'loc': ('body', 'data', 'id'), 'msg': 'Field required'}, {'type': 'missing', 'loc': ('body', 'data', 'round_key'), 'msg': 'Field required'}, {'type': 'missing', 'loc': ('body', 'data', 'item_list'), 'msg': 'Field required'}],)
[WARNING][2026-02-07 14:25:27,972][log.py:249]Unprocessable Content: /api/project/round/create_influence
[WARNING][2026-02-07 14:25:49,141][operation.py:131]"POST - RoundController[post_influence] /api/project/round/create_influence" ([{'type': 'missing', 'loc': ('body', 'data', 'id'), 'msg': 'Field required'}, {'type': 'missing', 'loc': ('body', 'data', 'round_key'), 'msg': 'Field required'}, {'type': 'missing', 'loc': ('body', 'data', 'item_list'), 'msg': 'Field required'}],)
[WARNING][2026-02-07 14:25:49,154][log.py:249]Unprocessable Content: /api/project/round/create_influence
[WARNING][2026-02-07 15:01:21,250][operation.py:131]"POST - RoundController[post_influence] /api/project/round/create_influence" ('Cannot assign "<QuerySet [<InfluenceArea: InfluenceArea object (195)>]>": "InfluenceItem.influence" must be a "InfluenceArea" instance.',)
[ERROR][2026-02-07 15:01:21,250][errors.py:131]Cannot assign "<QuerySet [<InfluenceArea: InfluenceArea object (195)>]>": "InfluenceItem.influence" must be a "InfluenceArea" instance.
Traceback (most recent call last):
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\operation.py", line 212, in run
result = self.view_func(request, **ctx.kwargs["view_func_kwargs"])
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\ninja_extra\controllers\route\route_functions.py", line 108, in as_view
result = self.route.view_func(
ctx.controller_instance, *args, **ctx.view_func_kwargs
)
File "D:\programs\uv\python\cpython-3.13.11-windows-x86_64-none\Lib\contextlib.py", line 85, in inner
return func(*args, **kwds)
File "E:\pycharmProjects\cdtestplant_v1\apps\project\controllers\round.py", line 110, in post_influence
new_item = InfluenceItem(influence=influence_area_qs,
change_type=item.change_type,
change_des=item.change_des,
effect_cases=item.effect_cases)
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\base.py", line 566, in __init__
_setattr(self, field.name, rel_obj)
~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "E:\pycharmProjects\cdtestplant_v1\.venv\Lib\site-packages\django\db\models\fields\related_descriptors.py", line 287, in __set__
raise ValueError(
...<7 lines>...
)
ValueError: Cannot assign "<QuerySet [<InfluenceArea: InfluenceArea object (195)>]>": "InfluenceItem.influence" must be a "InfluenceArea" instance.
[ERROR][2026-02-07 15:01:21,258][log.py:249]Internal Server Error: /api/project/round/create_influence
[WARNING][2026-02-07 15:19:38,249][operation.py:131]"POST - RoundController[post_influence] /api/project/round/create_influence" ([{'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 0), 'msg': 'Input should be a valid string'}, {'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 1), 'msg': 'Input should be a valid string'}],)
[WARNING][2026-02-07 15:19:38,257][log.py:249]Unprocessable Content: /api/project/round/create_influence
[WARNING][2026-02-07 15:19:43,626][operation.py:131]"POST - RoundController[post_influence] /api/project/round/create_influence" ([{'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 0), 'msg': 'Input should be a valid string'}, {'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 1), 'msg': 'Input should be a valid string'}],)
[WARNING][2026-02-07 15:19:43,635][log.py:249]Unprocessable Content: /api/project/round/create_influence
[WARNING][2026-02-07 15:20:44,492][operation.py:131]"POST - RoundController[post_influence] /api/project/round/create_influence" ([{'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 0), 'msg': 'Input should be a valid string'}, {'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 1), 'msg': 'Input should be a valid string'}],)
[WARNING][2026-02-07 15:20:44,503][log.py:249]Unprocessable Content: /api/project/round/create_influence
[WARNING][2026-02-07 15:21:39,506][operation.py:131]"POST - RoundController[post_influence] /api/project/round/create_influence" ([{'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 0), 'msg': 'Input should be a valid string'}, {'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 1), 'msg': 'Input should be a valid string'}, {'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 2), 'msg': 'Input should be a valid string'}, {'type': 'string_type', 'loc': ('body', 'data', 'item_list', 0, 'effect_cases', 3), 'msg': 'Input should be a valid string'}],)
[WARNING][2026-02-07 15:21:39,515][log.py:249]Unprocessable Content: /api/project/round/create_influence

Binary file not shown.

Binary file not shown.