refactor: P4c 批次1 服务层改造(notice/param/link/level)

【服务层新范式批量铺开】4 个 uniform 模块:
- service:get_x_page(params)->dict、add/update/status(data)->None、
  delete(ids)->int、get_info 委托 Repository(新建 repository.py)
- 业务失败 raise BizError;router 取参包 R
- level 的 Excel import/export 暂保留 R 返回(后续统一改造)

【工具】codemod 函数级转换(try/except 退格移除、R.failed→BizError、
R.ok→return data)+ black 格式化 + 未用导入清理

【教训】清理脚本 startswith 前缀误删含多名字的 import 行(models_to_list,
model_to_dict 同行)导致 F821,已按 F821 精确补回

【验收】应用启动;4 服务分页查询运行时正常;12 passed;flake8 零告警

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
DjangoAdmin Dev
2026-08-07 15:15:22 +08:00
co-authored by Claude
parent 63afa4e629
commit 3f55f62f0d
17 changed files with 570 additions and 656 deletions
-1
View File
@@ -50,7 +50,6 @@ from src.common.base_db import BaseDB
from src.common.base_model import BaseModel
from config import DB_PREFIX
from src.core.database import db
from src.common.utils.case_converter import convert_camel_to_snake
# ============================================================
+15
View File
@@ -0,0 +1,15 @@
"""
Link 仓储模块
=============================================================
数据访问层,继承 BaseRepository 获得通用 CRUD 能力。
"""
from src.common.base_repository import BaseRepository
from src.modules.cms.link.models import Link
class LinkRepository(BaseRepository):
"""Link 仓储"""
model = Link
+36 -20
View File
@@ -55,22 +55,24 @@
application.middleware.check_permission - 权限校验中间件
"""
from flask import Blueprint
from flask import Blueprint, request
from application.middleware.check_demo import check_demo
from application.middleware.check_permission import check_permission
from src.modules.cms.link import service as link
from src.common.utils.request import parse_batch_ids
link_blue = Blueprint('link', __name__, url_prefix='/link')
from src.common.utils.request import parse_batch_ids, parse_request_body
from src.core import response as R
link_blue = Blueprint("link", __name__, url_prefix="/link")
# ============================================================
# 友链分页查询
# ============================================================
@link_blue.route('/page', methods=["GET"])
@link_blue.route("/page", methods=["GET"])
@check_permission("sys:link:page")
def page():
"""
@@ -82,15 +84,15 @@ def page():
Returns:
JSON: 友链分页数据,包含 records(数据列表)、total(总记录数)等
"""
result = link.get_link_page()
return result
return R.ok(data=link.get_link_page(request.args))
# ============================================================
# 友链详情查询
# ============================================================
@link_blue.route('/detail/<int:id>', methods=["GET"])
@link_blue.route("/detail/<int:id>", methods=["GET"])
@check_permission("sys:link:detail")
def detail(id):
"""
@@ -110,7 +112,8 @@ def detail(id):
# 友链添加
# ============================================================
@link_blue.route('/add', methods=["POST"])
@link_blue.route("/add", methods=["POST"])
@check_permission("sys:link:add")
@check_demo
def add():
@@ -123,15 +126,19 @@ def add():
Returns:
JSON: 操作结果
"""
result = link.add_link()
return result
json_data, err = parse_request_body()
if err:
return R.failed(msg=err)
link.add_link(json_data)
return R.ok(msg="添加成功")
# ============================================================
# 友链更新
# ============================================================
@link_blue.route('/update', methods=["PUT"])
@link_blue.route("/update", methods=["PUT"])
@check_permission("sys:link:update")
@check_demo
def update():
@@ -144,15 +151,19 @@ def update():
Returns:
JSON: 操作结果
"""
result = link.update_link()
return result
json_data, err = parse_request_body()
if err:
return R.failed(msg=err)
link.update_link(json_data)
return R.ok(msg="更新成功")
# ============================================================
# 友链删除
# ============================================================
@link_blue.route('/delete/<string:id>', methods=["DELETE"])
@link_blue.route("/delete/<string:id>", methods=["DELETE"])
@check_permission("sys:link:delete")
@check_demo
def delete(id):
@@ -165,15 +176,16 @@ def delete(id):
Returns:
JSON: 操作结果
"""
result = link.delete_links(id)
return result
count = link.delete_links(id)
return R.ok(msg=f"本次共删除{count}条数据")
# ============================================================
# 友链批量删除
# ============================================================
@link_blue.route('/batchDelete', methods=["DELETE"])
@link_blue.route("/batchDelete", methods=["DELETE"])
@check_permission("sys:link:batch_delete")
@check_demo
def batch_delete():
@@ -199,7 +211,8 @@ def batch_delete():
# 友链状态设置
# ============================================================
@link_blue.route('/status', methods=["PUT"])
@link_blue.route("/status", methods=["PUT"])
@check_permission("sys:link:status")
@check_demo
def status():
@@ -212,5 +225,8 @@ def status():
Returns:
JSON: 操作结果
"""
result = link.update_link_status()
return result
json_data, err = parse_request_body()
if err:
return R.failed(msg=err)
link.update_link_status(json_data)
return R.ok(msg="更新成功")
+97 -152
View File
@@ -65,19 +65,17 @@
import logging
from datetime import datetime, timezone
from flask import request
from sqlalchemy import and_
from src.common.constants.common import PAGE_SIZE
from src.common.constants.dictionary_constants import LINK_TYPE_LIST, LINK_FORM_LIST
from src.modules.cms.link.schema import LinkForm, LinkStatusForm
from src.modules.cms.link.models import Link
from src.core.database import db
from src.core import response as R
from src.modules.cms.link.repository import LinkRepository
from src.core.exceptions import BizError
from src.common.utils import regular
from src.common.utils.case_converter import convert_camel_to_snake
from src.common.utils.model_utils import models_to_list, model_to_dict
from src.common.utils.request import parse_request_body, parse_id_list, like_contains
from src.common.utils.model_utils import model_to_dict
from src.common.utils.request import parse_id_list, like_contains
from src.common.utils.rich_text import get_file_url, save_file
from src.core.security import get_username
@@ -89,7 +87,8 @@ logger = logging.getLogger(__name__)
# 友链分页查询
# ============================================================
def get_link_page():
def get_link_page(params: dict) -> dict:
"""
查询友链分页数据
@@ -112,31 +111,26 @@ def get_link_page():
"pages": 总页数
}
"""
try:
# 获取分页参数
page_no = int(request.args.get('pageNo', 1))
page_size = int(request.args.get('pageSize', PAGE_SIZE))
# 获取分页参数
page_no = int(params.get("pageNo", 1))
page_size = int(params.get("pageSize", PAGE_SIZE))
# 应用筛选条件
query = _apply_filters()
# 应用筛选条件
query = _apply_filters(params)
# 记录总数
total = query.count()
# 计算总页数
pages = (total + page_size - 1) // page_size if total > 0 else 0
# 记录总数
total = query.count()
# 计算总页数
pages = (total + page_size - 1) // page_size if total > 0 else 0
# 分页查询
link_list = query.limit(page_size).offset((page_no - 1) * page_size).all()
# 构建返回数据
page_data = _build_page_data(link_list, total, page_size, page_no, pages)
return R.ok(data=page_data)
except Exception as e:
logger.error(f"查询友链分页数据异常: {str(e)}")
return R.failed(msg="查询失败,请稍后重试")
# 分页查询
link_list = query.limit(page_size).offset((page_no - 1) * page_size).all()
# 构建返回数据
page_data = _build_page_data(link_list, total, page_size, page_no, pages)
return page_data
def _apply_filters():
def _apply_filters(params: dict):
"""
应用查询筛选条件
@@ -156,22 +150,22 @@ def _apply_filters():
query = Link.query.filter(Link.is_delete == 0)
# 友链名称模糊筛选
name = request.args.get('name')
name = params.get("name")
if name:
query = query.filter(Link.name.like(like_contains(name), escape='\\'))
query = query.filter(Link.name.like(like_contains(name), escape="\\"))
# 友链类型精确筛选
link_type = request.args.get('type')
link_type = params.get("type")
if link_type:
query = query.filter(Link.type == link_type)
# 友链形式精确筛选
form = request.args.get('form')
form = params.get("form")
if form:
query = query.filter(Link.form == form)
# 友链状态精确筛选
status = request.args.get('status')
status = params.get("status")
if status:
query = query.filter(Link.status == status)
@@ -198,27 +192,22 @@ def _build_page_data(link_list, total, page_size, page_no, pages):
for item in link_list:
data = model_to_dict(item)
# 添加友链类型描述
data['typeName'] = LINK_TYPE_LIST.get(item.type)
data["typeName"] = LINK_TYPE_LIST.get(item.type)
# 添加友链形式描述
data['formName'] = LINK_FORM_LIST.get(item.form)
data["formName"] = LINK_FORM_LIST.get(item.form)
# 友链图片URL
if item.image:
data['image'] = get_file_url(item.image)
data["image"] = get_file_url(item.image)
records.append(data)
return {
'records': records,
'total': total,
'size': page_size,
'current': page_no,
'pages': pages
}
return {"records": records, "total": total, "size": page_size, "current": page_no, "pages": pages}
# ============================================================
# 友链详情查询
# ============================================================
def get_link_detail(link_id):
"""
根据ID查询友链详情(返回字典格式)
@@ -241,7 +230,7 @@ def get_link_detail(link_id):
data = model_to_dict(link)
# 友链图片URL
if link.image:
data['image'] = get_file_url(link.image)
data["image"] = get_file_url(link.image)
return data
except Exception as e:
@@ -253,6 +242,7 @@ def get_link_detail(link_id):
# 友链信息查询(根据ID)- 核心查询方法
# ============================================================
def get_info(link_id: int):
"""
根据ID查询友链信息(返回模型对象)
@@ -278,26 +268,10 @@ def get_info(link_id: int):
if link:
print(link.name)
"""
# 参数有效性验证
if not link_id or link_id <= 0:
return None
try:
# 查询未删除的友链
link = Link.query.filter(
and_(Link.id == link_id, Link.is_delete == 0)
).first()
return link
except Exception as e:
logger.error(f"查询友链信息异常,ID: {link_id}, 错误: {str(e)}")
return None
return LinkRepository.get_by_id(link_id)
# ============================================================
# 友链添加
# ============================================================
def add_link():
def add_link(data: dict) -> None:
"""
添加友链
@@ -310,40 +284,29 @@ def add_link():
Returns:
R: 操作结果
"""
try:
# 获取参数
json_data, error = parse_request_body()
if error:
return R.failed(msg=error)
# 表单验证
form = LinkForm(data=json_data)
if not form.validate():
err_msg = regular.get_err(form)
return R.failed(msg=err_msg)
# 表单验证
form = LinkForm(data=data)
if not form.validate():
raise BizError(regular.get_err(form))
# 处理友链图片
image = form.data.get('image')
if image:
form.image.data = save_file(image, "link")
# 处理友链图片
image = form.data.get("image")
if image:
form.image.data = save_file(image, "link")
# 创建友链
link = Link(**form.data)
link.create_user = get_username()
link.save()
return R.ok(msg="添加成功")
except Exception as e:
logger.error(f"添加友链异常: {str(e)}")
return R.failed(msg="添加失败,请稍后重试")
# 创建友链
link = Link(**form.data)
link.create_user = get_username()
link.save()
# ============================================================
# 友链更新
# ============================================================
def update_link():
def update_link(data: dict) -> None:
"""
更新友链
@@ -357,57 +320,47 @@ def update_link():
Returns:
R: 操作结果
"""
try:
# 获取参数
json_data, error = parse_request_body()
if error:
return R.failed(msg=error)
# 表单验证
form = LinkForm(data=json_data)
if not form.validate():
return R.failed(msg=regular.get_err(form))
# 表单验证
form = LinkForm(data=data)
if not form.validate():
raise BizError(regular.get_err(form))
# 获取友链ID
link_id = form.data.get('id')
if not link_id or int(link_id) <= 0:
return R.failed("友链ID无效")
link_id = int(link_id)
# 获取友链ID
link_id = form.data.get("id")
if not link_id or int(link_id) <= 0:
raise BizError("友链ID无效")
link_id = int(link_id)
# 复用 get_info 方法验证友链是否存在
link = get_info(link_id)
if not link:
return R.failed("友链不存在")
# 复用 get_info 方法验证友链是否存在
link = get_info(link_id)
if not link:
raise BizError("友链不存在")
# 处理友链图片
image = form.data.get('image')
if image:
form.image.data = save_file(image, "link")
# 处理友链图片
image = form.data.get("image")
if image:
form.image.data = save_file(image, "link")
# 更新友链信息(移除ID,避免更新主键)
form_data = convert_camel_to_snake(form.data.copy())
form_data.pop('id', None)
# 更新友链信息(移除ID,避免更新主键)
form_data = convert_camel_to_snake(form.data.copy())
form_data.pop("id", None)
form_data['update_time'] = datetime.now(tz=timezone.utc)
form_data['update_user'] = get_username()
form_data["update_time"] = datetime.now(tz=timezone.utc)
form_data["update_user"] = get_username()
result = Link.query.filter_by(id=link_id).update(form_data)
result = Link.query.filter_by(id=link_id).update(form_data)
if not result:
return R.failed("更新失败")
return R.ok(msg="更新成功")
except Exception as e:
logger.error(f"更新友链异常: {str(e)}")
return R.failed(msg="更新友链失败,请稍后重试")
if not result:
raise BizError("更新失败")
# ============================================================
# 友链删除
# ============================================================
def delete_links(link_ids):
def delete_links(link_ids: str) -> int:
"""
删除友链(批量删除)
@@ -420,14 +373,18 @@ def delete_links(link_ids):
Returns:
R: 操作结果
"""
return Link.batch_delete_r(link_ids)
link_ids_list = parse_id_list(link_ids)
if not link_ids_list:
raise BizError("无效的记录ID")
return Link.batch_delete(link_ids_list)
# ============================================================
# 友链状态设置
# ============================================================
def update_link_status():
def update_link_status(data: dict) -> None:
"""
设置友链状态
@@ -436,35 +393,23 @@ def update_link_status():
Returns:
R: 操作结果
"""
try:
# 获取参数
json_data, error = parse_request_body()
if error:
return R.failed(msg=error)
# 表单验证
form = LinkStatusForm(data=json_data)
if not form.validate():
err_msg = regular.get_err(form)
return R.failed(msg=err_msg)
# 表单验证
form = LinkStatusForm(data=data)
if not form.validate():
raise BizError(regular.get_err(form))
link_id = int(form.data['id'])
status = int(form.data['status'])
link_id = int(form.data["id"])
status = int(form.data["status"])
# 复用 get_info 方法验证友链是否存在
link = get_info(link_id)
if not link:
return R.failed("友链不存在")
# 复用 get_info 方法验证友链是否存在
link = get_info(link_id)
if not link:
raise BizError("友链不存在")
# 更新状态
update_data = {"status": status, "update_time": datetime.now(tz=timezone.utc), "update_user": get_username()}
result = Link.query.filter_by(id=link_id).update(update_data)
# 更新状态
update_data = {"status": status, "update_time": datetime.now(tz=timezone.utc), "update_user": get_username()}
result = Link.query.filter_by(id=link_id).update(update_data)
if not result:
return R.failed("设置失败")
return R.ok(msg="设置成功")
except Exception as e:
logger.error(f"设置友链状态异常: {str(e)}")
return R.failed(msg="设置友链状态失败,请稍后重试")
if not result:
raise BizError("设置失败")