完成项目管理模块的接口测试

This commit is contained in:
sunyugang 2025-04-18 17:22:57 +08:00
parent 434e1af3e8
commit 7a9e571a96
16 changed files with 91 additions and 74 deletions

View File

@ -29,7 +29,6 @@ MONGO_DB_ENABLE = False
MONGO_DB_NAME = "kinit"
MONGO_DB_URL = f"mongodb://kinit:123456@177.8.0.6:27017/?authSource={MONGO_DB_NAME}"
"""
华为云对象存储OBS设置
"""
@ -47,10 +46,16 @@ HUAWEI_OBS = {
IP_PARSE_ENABLE = False
IP_PARSE_TOKEN = "IP_PARSE_TOKEN"
datasets_url = f'D:\syg\yolov5\datasets'
runs_url = f'D:\syg\yolov5\runs'
detect_url = f'D:\syg\yolov5\detect'
yolo_url = f'D:\syg\workspace\aicheckv2\yolov5'
images_url = f'D:\syg\images'
"""
yolov5的各种文件保存地址
images_url 原始图片保存地址
datasets_url 文件集文件地址
runs_url 训练结果文件地址
detect_url 推理集合文件地址
yolo_url yolov5执行文件所在的文件路径
"""
images_url = r'D:\syg\images'
datasets_url = r'D:\syg\yolov5\datasets'
runs_url = r'D:\syg\yolov5\runs'
detect_url = r'D:\syg\yolov5\detect'
yolo_url = r'D:\syg\workspace\aicheckv2\yolov5'

View File

@ -28,7 +28,6 @@ MONGO_DB_ENABLE = False
MONGO_DB_NAME = "kinit"
MONGO_DB_URL = f"mongodb://kinit:123456@177.8.0.6:27017/?authSource={MONGO_DB_NAME}"
"""
华为云对象存储OBS设置
"""
@ -39,7 +38,6 @@ HUAWEI_OBS = {
"bucketName": "aicheckv2"
}
"""
获取IP地址归属地
文档https://user.ip138.com/ip/doc
@ -47,9 +45,16 @@ HUAWEI_OBS = {
IP_PARSE_ENABLE = False
IP_PARSE_TOKEN = "IP_PARSE_TOKEN"
"""
yolov5的各种文件保存地址
images_url 原始图片保存地址
datasets_url 待训练文件地址
runs_url 训练结果文件地址
detect_url 推理集合文件地址
yolo_url yolo执行文件所在的文件路径
"""
images_url = f'/home/aicheckv2/images'
datasets_url = f'/home/aicheckv2/yolov5/datasets'
runs_url = f'/home/aicheckv2/yolov5/runs'
detect_url = f'/home/aicheckv2/yolov5/detect'
yolo_url = f'/home/aicheckv2/backend/yolov5'
images_url = f'/home/aicheckv2/images'

View File

@ -12,7 +12,7 @@ from . import schemas, models
from utils.random_utils import random_str
from utils import os_utils as os
from application.settings import detect_url
from utils.huawei_obs import ObsClient
from utils.huawei_obs import MyObs
from utils import status
from core.exception import CustomException
@ -76,6 +76,7 @@ class ProjectDetectFileDal(DalBase):
async def add_file(self, detect: models.ProjectDetect, files: list[UploadFile]):
images = []
obs = MyObs()
for file in files:
image = models.ProjectDetectFile()
image.detect_id = detect.id
@ -85,7 +86,7 @@ class ProjectDetectFileDal(DalBase):
image.image_url = path
# 上传到obs
object_key = detect.detect_no + '/' + file.filename
success, key, url = ObsClient.put_file(object_key=object_key, file_path=path)
success, key, url = obs.put_file(object_key=object_key, file_path=path)
if success:
image.object_key = object_key
image.thumb_image_url = url
@ -103,7 +104,7 @@ class ProjectDetectFileDal(DalBase):
file_urls.append(file.file_url)
object_keys.append(file.object_key)
os.delete_paths(file_urls)
ObsClient.del_objects(object_keys)
MyObs().del_objects(object_keys)
await self.delete_datas(ids, v_soft=False)
class ProjectDetectLogDal(DalBase):

View File

@ -8,7 +8,7 @@
from . import schemas, models, params
from apps.vadmin.auth.utils.validation.auth import Auth
from utils import os_utils as os, random_utils as ru
from utils.huawei_obs import ObsClient
from utils.huawei_obs import MyObs
from utils import status
from core.exception import CustomException
from application.settings import datasets_url, runs_url, images_url
@ -169,6 +169,7 @@ class ProjectImageDal(DalBase):
上传项目图片
"""
image_models = []
obs = MyObs()
for file in files:
image = models.ProjectImage()
image.project_id = pro.id
@ -179,14 +180,14 @@ class ProjectImageDal(DalBase):
image.image_url = path
# 上传图片到obs
object_key = pro.project_no + '/' + img_type + '/' + file.filename
success, key, url = ObsClient.put_file(object_key=object_key, file_path=path)
success, key, url = obs.put_file(object_key=object_key, file_path=path)
if success:
image.object_key = object_key
image.thumb_image_url = url
else:
raise CustomException("obs上传失败", code=status.HTTP_ERROR)
image_models.append(image)
await self.create_datas(datas=image_models)
await self.create_models(datas=image_models)
return len(image_models)
async def check_img_name(self, file_name: str, project_id: int, img_type: str):
@ -207,12 +208,12 @@ class ProjectImageDal(DalBase):
file_urls = []
object_keys = []
for img_id in ids:
image = self.get_data(data_id=img_id)
image = await self.get_data(data_id=img_id)
if image:
file_urls.append(image.image_url)
object_keys.append(image.object_key)
os.delete_file_if_exists(**file_urls)
ObsClient.del_objects(object_keys)
os.delete_file_if_exists(*file_urls)
MyObs().del_objects(object_keys)
await self.delete_datas(ids)
async def get_img_count(
@ -330,6 +331,11 @@ class ProjectImgLabelDal(DalBase):
v_order="asc",
v_order_field="id")
async def del_img_label(self, label_ids: list[int]):
img_labels = self.get_datas(v_where=[self.model.label_id.in_(label_ids)])
img_label_ids = [i.id for i in img_labels]
self.delete_datas(ids=img_label_ids)
class ProjectImgLeaferDal(DalBase):
"""
@ -342,6 +348,10 @@ class ProjectImgLeaferDal(DalBase):
self.model = models.ProjectImgLeafer
self.schema = schemas.ProjectImgLeaferOut
async def get_leafer(self, image_id: int):
img_label = self.get_data(v_where=[self.model.image_id == image_id])
return img_label.leafer
async def add_leafer(self, img_label_in: schemas.ProjectImgLeaferLabel):
# 先把历史数据都删掉,然后再保存
image_id = img_label_in.image_id

View File

@ -16,7 +16,7 @@ class ProjectImage(BaseModel):
project_id: Optional[int] = Field(..., description="项目id")
file_name: Optional[str] = Field(None, description="文件名称")
thumb_image_url: Optional[str] = Field(None, description="图片在obs上的链接")
create_time: DatetimeStr
create_datetime: DatetimeStr
model_config = ConfigDict(from_attributes=True)
@ -26,7 +26,7 @@ class ProjectImageOut(BaseModel):
project_id: Optional[int] = Field(..., description="项目id")
file_name: Optional[str] = Field(None, description="文件名称")
thumb_image_url: Optional[str] = Field(None, description="图片在obs上的链接")
create_time: DatetimeStr
label_count: Optional[int]
label_count: Optional[int] = Field(0, description="图片的标注数量")
create_datetime: DatetimeStr
model_config = ConfigDict(from_attributes=True)

View File

@ -5,11 +5,11 @@
# @File : views.py
# @IDE : PyCharm
# @desc : 路由,项目信息管理,包括项目主体,项目图片,项目标签和图片的标注信息
from utils.response import SuccessResponse, ErrorResponse
from . import params, schemas, crud, models
from core.dependencies import IdList
from typing import List
from core.dependencies import IdList
from . import params, schemas, crud, models
from utils.response import SuccessResponse, ErrorResponse
from fastapi import APIRouter, Depends, UploadFile, Form
from apps.vadmin.auth.utils.current import FullAdminAuth
from apps.vadmin.auth.utils.validation.auth import Auth
@ -60,12 +60,12 @@ async def del_project(
return SuccessResponse(msg="删除成功")
@app.get("/label/{pro_id}", summary="查询标签列表")
@app.get("/label/{project_id}", summary="查询标签列表")
async def label_list(
pro_id: int,
project_id: int,
auth: Auth = Depends(FullAdminAuth())
):
result = await crud.ProjectLabelDal(auth.db).get_datas(v_where=[models.ProjectLabel.project_id == pro_id],
result = await crud.ProjectLabelDal(auth.db).get_datas(v_where=[models.ProjectLabel.project_id == project_id],
v_schema=schemas.ProjectLabel)
return SuccessResponse(data=result)
@ -101,8 +101,7 @@ async def delete_label(
):
# 删除标签信息,然后删除图片标签关联表
await crud.ProjectLabelDal(auth.db).delete_datas(label_ids.ids)
for label_id in label_ids.ids:
await crud.ProjectImgLabelDal(auth.db).delete_datas(label_id=label_id)
await crud.ProjectImgLabelDal(auth.db).del_img_label(label_ids.ids)
return SuccessResponse(msg="删除成功")
@ -111,7 +110,7 @@ async def project_pager(
param: params.ProjectImageParams = Depends(),
auth: Auth = Depends(FullAdminAuth())
):
if param.limit:
if param.limit > 0:
# 分页查询,关联一个标签数量
datas, count = await crud.ProjectImageDal(auth.db).img_page(param)
return SuccessResponse(data=datas, count=count)
@ -124,7 +123,7 @@ async def project_pager(
@app.post("/img", summary="上传图片")
async def up_img(
project_id: int = Form(...),
files: List[UploadFile] = Form(...),
files: list[UploadFile] = Form(...),
img_type: str = Form(...),
auth: Auth = Depends(FullAdminAuth())
):
@ -155,8 +154,10 @@ async def add_img_label(
return SuccessResponse(msg="保存成功")
@app.get("/img_label/{image_id}", summary="获取图片的标注信息")
async def get_img_label(
image_id: int,
auth: Auth = Depends(FullAdminAuth())
):
leafer = await crud.ProjectImgLeaferDal(auth.db).get_leafer(image_id)
return SuccessResponse(data=leafer)

View File

@ -18,7 +18,7 @@ from sqlalchemy import select, false, and_
from core.crud import DalBase
from sqlalchemy.ext.asyncio import AsyncSession
from core.validator import vali_telephone
from utils.huawei_obs import ObsClient
from utils.huawei_obs import MyObs
from utils.excel.import_manage import ImportManage, FieldType
from utils.excel.write_xlsx import WriteXlsx
from utils.send_email import EmailSender
@ -221,8 +221,6 @@ class UserDal(DalBase):
value = getattr(user, field, "")
if field == "is_active":
value = "可用" if value else "停用"
elif field == "is_staff":
value = "" if value else ""
elif field == "gender":
result = list(filter(lambda i: i["value"] == value, options["gender_options"]))
value = result[0]["label"] if result else ""
@ -397,7 +395,7 @@ class UserDal(DalBase):
:param file:
:return:
"""
success, key, url = await ObsClient().put_object("avatar"+"/"+user.name+file.filename, file)
success, key, url = MyObs().put_object("avatar"+"/"+user.name+file.filename, file)
user.avatar = url
await self.flush(user)
return url

View File

@ -37,7 +37,6 @@ class VadminUser(BaseModel):
)
last_ip: Mapped[str | None] = mapped_column(String(50), comment="最后一次登录IP")
last_login: Mapped[datetime | None] = mapped_column(DateTime, comment="最近一次登录时间")
is_staff: Mapped[bool] = mapped_column(Boolean, default=False, comment="是否为工作人员")
wx_server_openid: Mapped[str | None] = mapped_column(String(255), comment="服务端微信平台openid")
is_wx_server_openid: Mapped[bool] = mapped_column(Boolean, default=False, comment="是否已有服务端微信平台openid")

View File

@ -24,7 +24,6 @@ class UserParams(QueryParams):
telephone: str | None = Query(None, title="手机号"),
email: str | None = Query(None, title="邮箱"),
is_active: bool | None = Query(None, title="是否可用"),
is_staff: bool | None = Query(None, title="是否为工作人员"),
params: Paging = Depends()
):
super().__init__(params)
@ -32,6 +31,5 @@ class UserParams(QueryParams):
self.telephone = ("like", telephone)
self.email = ("like", email)
self.is_active = is_active
self.is_staff = is_staff

View File

@ -21,7 +21,6 @@ class User(BaseModel):
nickname: str | None = None
avatar: str | None = None
is_active: bool | None = True
is_staff: bool | None = True
gender: str | None = "0"
is_wx_server_openid: bool | None = False
@ -56,7 +55,6 @@ class UserUpdate(User):
nickname: str | None = None
avatar: str | None = None
is_active: bool | None = True
is_staff: bool | None = False
gender: str | None = "0"
role_ids: list[int] = []
dept_ids: list[int] = []

View File

@ -103,8 +103,7 @@ class FullAdminAuth(AuthValidation):
telephone=telephone,
password=password,
v_return_none=True,
v_options=options,
is_staff=True
v_options=options
)
result = await self.validate_user(request, user, db, is_all=False)
permissions = self.get_user_permissions(user)

View File

@ -57,8 +57,6 @@ async def api_login_for_access_token(
raise CustomException(status_code=error_code, code=error_code, msg="手机号或密码错误")
if not user.is_active:
raise CustomException(status_code=error_code, code=error_code, msg="此手机号已被冻结")
elif not user.is_staff:
raise CustomException(status_code=error_code, code=error_code, msg="此手机号无权限")
access_token = LoginManage.create_token({"sub": user.telephone, "password": user.password})
record = LoginForm(platform='2', method='0', telephone=data.username, password=data.password)
resp = {"access_token": access_token, "token_type": "bearer"}

View File

@ -80,7 +80,7 @@ class LoginValidation:
await db.flush()
elif not user.is_active:
self.result.msg = "此手机号已被冻结!"
elif data.platform in ["0", "1"] and not user.is_staff:
elif data.platform in ["0", "1"]:
self.result.msg = "此手机号无权限!"
else:
if not DEMO and count:

View File

@ -6,19 +6,14 @@
# @desc : 主要接口文件
from redis.asyncio import Redis
from fastapi import APIRouter, Depends, Body, UploadFile, Form, Request
from fastapi import APIRouter, Depends, Body
from motor.motor_asyncio import AsyncIOMotorDatabase
from sqlalchemy.ext.asyncio import AsyncSession
from application.settings import ALIYUN_OSS
from core.database import db_getter, redis_getter, mongo_getter
from utils.file.aliyun_oss import AliyunOSS, BucketConf
from utils.huawei_obs import ObsClient
from utils.file.file_manage import FileManage
from core.database import redis_getter, mongo_getter
from utils.response import SuccessResponse, ErrorResponse
from utils.sms.code import CodeSMS
from . import schemas, crud
from core.dependencies import IdList
from apps.vadmin.auth.utils.current import AllUserAuth, FullAdminAuth, OpenAuth
from apps.vadmin.auth.utils.current import AllUserAuth, OpenAuth
from apps.vadmin.auth.utils.validation.auth import Auth
from .params import DictTypeParams, DictDetailParams, TaskParams
from apps.vadmin.auth import crud as vadmin_auth_crud

View File

@ -263,6 +263,16 @@ class DalBase:
await self.db.execute(insert(self.model), datas)
await self.db.flush()
async def create_models(self, datas: list[Any]) -> None:
"""
批量创建数据
SQLAlchemy 2.0 批量插入不支持 MySQL 返回值
https://docs.sqlalchemy.org/en/20/orm/queryguide/dml.html#getting-new-objects-with-returning
:param datas: model数组
"""
self.db.add_all(datas)
await self.db.flush()
async def put_data(
self,
data_id: int,

View File

@ -5,28 +5,28 @@ from obs import DeleteObjectsRequest
from obs import Object
class ObsClient:
class MyObs:
def __int__(self):
def __init__(self):
self.obsClient = ObsClient(
access_key_id=HUAWEI_OBS['AccessKeyID'],
secret_access_key=HUAWEI_OBS['SecretAccessKey'],
server=HUAWEI_OBS["server"])
async def put_file(self, objectKey: str, file_path: str):
resp = await self.obsClient.putFile(
def put_file(self, object_key: str, file_path: str):
resp = self.obsClient.putFile(
bucketName=HUAWEI_OBS["bucketName"],
objectKey=objectKey,
objectKey=object_key,
file_path=file_path)
if resp.status < 300:
print("objectKey", objectKey)
print("objectKey", object_key)
print("url", resp.body.objectUrl)
return True, objectKey, resp.body.objectUrl
return True, object_key, resp.body.objectUrl
else:
return False, None, None
async def put_object(self, objectKey: str, file_content):
resp = await self.obsClient.put_object(
def put_object(self, objectKey: str, file_content):
resp = self.obsClient.put_object(
bucketName=HUAWEI_OBS["bucketName"],
objectKey=objectKey,
file_cotent=file_content)
@ -37,14 +37,14 @@ class ObsClient:
else:
return False, None, None
async def del_objects(self, object_keys: []):
def del_objects(self, object_keys: []):
objects = []
for object_key in object_keys:
object_one = Object(key=object_key, versionId=None)
objects.append(object_one)
encoding_type = 'url'
resp = await self.obsClient.deleteObjects(
resp = self.obsClient.deleteObjects(
bucketName=HUAWEI_OBS["bucketName"],
deleteObjectsRequest=DeleteObjectsRequest(quiet=False, objects=objects, encoding_type=encoding_type))
if resp.status < 300: