mirror of
https://github.com/fastapiadmin/FastapiAdmin.git
synced 2026-09-21 12:52:26 +00:00
feat: 优化表单提交逻辑和添加表单验证
refactor: 重构后端模型验证逻辑 fix: 修复资源文件路径处理和下载服务 style: 调整前端样式和布局 perf: 优化AI错误处理和提示信息 docs: 更新上传组件提示信息 test: 添加表单提交测试用例 chore: 更新依赖和配置文件
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from typing import Optional, List
|
||||
from pydantic import BaseModel, ConfigDict, Field, EmailStr, field_validator
|
||||
from pydantic import BaseModel, ConfigDict, Field, EmailStr, field_validator, model_validator
|
||||
|
||||
from app.core.validator import DateTimeStr, mobile_validator
|
||||
from app.core.base_schema import BaseSchema, CommonSchema
|
||||
from app.api.v1.module_system.role.schema import RoleOutSchema
|
||||
from urllib.parse import urlparse
|
||||
|
||||
class CurrentUserUpdateSchema(BaseModel):
|
||||
"""基础用户信息"""
|
||||
@@ -20,6 +21,16 @@ class CurrentUserUpdateSchema(BaseModel):
|
||||
def validate_mobile(cls, value: Optional[str]):
|
||||
return mobile_validator(value)
|
||||
|
||||
@field_validator("avatar")
|
||||
@classmethod
|
||||
def validate_avatar(cls, value: Optional[str]):
|
||||
if not value:
|
||||
return value
|
||||
parsed = urlparse(value)
|
||||
if parsed.scheme in ("http", "https") and parsed.netloc:
|
||||
return value
|
||||
raise ValueError("头像地址需为有效的HTTP/HTTPS URL")
|
||||
|
||||
|
||||
class UserRegisterSchema(BaseModel):
|
||||
"""注册"""
|
||||
@@ -36,6 +47,36 @@ class UserRegisterSchema(BaseModel):
|
||||
def validate_mobile(cls, value: Optional[str]):
|
||||
return mobile_validator(value)
|
||||
|
||||
@field_validator("username")
|
||||
@classmethod
|
||||
def validate_username(cls, value: str):
|
||||
v = value.strip()
|
||||
if not v:
|
||||
raise ValueError("账号不能为空")
|
||||
# 字母开头,允许字母数字_.-
|
||||
import re
|
||||
if not re.match(r"^[A-Za-z][A-Za-z0-9_.-]{2,31}$", v):
|
||||
raise ValueError("账号需字母开头,3-32位,仅含字母/数字/_ . -")
|
||||
return v
|
||||
|
||||
@model_validator(mode='before')
|
||||
@classmethod
|
||||
def _normalize(cls, values):
|
||||
if isinstance(values, dict):
|
||||
for k in ["name", "username", "password", "description"]:
|
||||
if k in values and isinstance(values[k], str):
|
||||
values[k] = values[k].strip() or values[k]
|
||||
# role_ids 去重并转为 int
|
||||
if "role_ids" in values and values["role_ids"] is not None:
|
||||
try:
|
||||
values["role_ids"] = list[int]({int(x) for x in values["role_ids"]})
|
||||
except Exception:
|
||||
pass
|
||||
# mobile 空串转 None
|
||||
if "mobile" in values and isinstance(values["mobile"], str) and values["mobile"].strip() == "":
|
||||
values["mobile"] = None
|
||||
return values
|
||||
|
||||
|
||||
class UserForgetPasswordSchema(BaseModel):
|
||||
"""忘记密码"""
|
||||
@@ -75,6 +116,35 @@ class UserCreateSchema(CurrentUserUpdateSchema):
|
||||
role_ids: Optional[List[int]] = Field(default=[], description='角色ID')
|
||||
position_ids: Optional[List[int]] = Field(default=[], description='岗位ID')
|
||||
|
||||
@model_validator(mode='before')
|
||||
@classmethod
|
||||
def _normalize(cls, values):
|
||||
if isinstance(values, dict):
|
||||
# 字符串去空格和空串转 None
|
||||
for k in ["username", "password", "description", "name"]:
|
||||
if k in values and isinstance(values[k], str):
|
||||
values[k] = values[k].strip() or None if values[k].strip() == "" else values[k].strip()
|
||||
# bool 兼容
|
||||
for k in ["status", "is_superuser"]:
|
||||
if k in values:
|
||||
v = values[k]
|
||||
if isinstance(v, str):
|
||||
values[k] = v.strip().lower() in {"true", "1", "yes", "y"}
|
||||
# 列表转 int 去重
|
||||
for k in ["role_ids", "position_ids"]:
|
||||
if k in values and values[k] is not None:
|
||||
try:
|
||||
values[k] = list({int(x) for x in values[k]})
|
||||
except Exception:
|
||||
pass
|
||||
return values
|
||||
|
||||
@model_validator(mode='after')
|
||||
def _validate_after(self):
|
||||
if self.status is False and (not self.description or not str(self.description).strip()):
|
||||
raise ValueError("禁用状态下必须填写备注描述")
|
||||
return self
|
||||
|
||||
|
||||
class UserUpdateSchema(UserCreateSchema):
|
||||
"""更新"""
|
||||
|
||||
Reference in New Issue
Block a user