153 lines
5.2 KiB
Python
153 lines
5.2 KiB
Python
from typing import Optional
|
||
|
||
from pydantic import BaseModel, Field, field_validator, ConfigDict
|
||
from datetime import datetime
|
||
|
||
|
||
class BlogQuery(BaseModel):
|
||
"""博客查询参数"""
|
||
category: Optional[str] = Field(None, description="分类名称")
|
||
title: Optional[str] = Field(None, description="标题关键词")
|
||
year: Optional[int] = Field(None, description="发布年份", ge=2000, le=datetime.now().year)
|
||
|
||
@field_validator('year')
|
||
def validate_year(cls, v):
|
||
if v is not None and v > datetime.now().year:
|
||
raise ValueError('年份不能超过当前年份')
|
||
return v
|
||
|
||
|
||
class BlogBase(BaseModel):
|
||
"""博客基础模型"""
|
||
title: str = Field(..., min_length=1, max_length=255, description="博客标题")
|
||
top_value: int = Field(default=0, ge=0, description="置顶值,越大越靠前", alias="topValue")
|
||
is_great: bool = Field(default=False, description="是否是精品", alias="isGreat")
|
||
category: str = Field(..., min_length=1, max_length=45, description="分类名称")
|
||
content: Optional[str] = Field(None, description="博客内容")
|
||
is_approved: bool = Field(default=False, description="是否已发布", alias="isApproved")
|
||
|
||
@field_validator('title')
|
||
def title_not_empty(cls, v):
|
||
if not v or not v.strip():
|
||
raise ValueError('标题不能为空')
|
||
return v.strip()
|
||
|
||
@field_validator('category')
|
||
def category_not_empty(cls, v):
|
||
if not v or not v.strip():
|
||
raise ValueError('分类不能为空')
|
||
return v.strip()
|
||
|
||
|
||
class BlogCreate(BlogBase):
|
||
pass
|
||
|
||
|
||
class BlogUpdate(BlogBase):
|
||
pass
|
||
|
||
|
||
class BlogResponse(BlogBase):
|
||
id: int = Field(..., description="博客ID")
|
||
summary: Optional[str] = Field(None, description="内容摘要")
|
||
word_count: Optional[int] = Field(None, description="字数统计", alias="wordCount")
|
||
read_duration: Optional[float] = Field(None, description="阅读时长", alias="readDuration")
|
||
visit_count: Optional[int] = Field(0, description="访问次数", alias="visitCount")
|
||
create_time: datetime = Field(..., description="创建时间", alias="createTime")
|
||
update_time: datetime = Field(..., description="更新时间", alias="updateTime")
|
||
|
||
model_config = ConfigDict(
|
||
from_attributes=True,
|
||
populate_by_name=True,
|
||
json_encoders={
|
||
datetime: lambda dt: dt.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
)
|
||
|
||
|
||
class BlogCategoryResponse(BaseModel):
|
||
name: str = Field(..., description="分类名称")
|
||
count: int = Field(..., description="博客数量")
|
||
|
||
model_config = ConfigDict(
|
||
from_attributes=True,
|
||
populate_by_name=True
|
||
)
|
||
|
||
|
||
class BlogStatsResponse(BaseModel):
|
||
blog_count: int = Field(..., description="博客总数", alias="blogCount")
|
||
category_count: int = Field(..., description="分类总数", alias="categoryCount")
|
||
word_count: int = Field(..., description="总字数", alias="wordCount")
|
||
|
||
|
||
class BlogVisitResponse(BaseModel):
|
||
ip: str = Field(..., description="IP地址")
|
||
os: str = Field(..., description="操作系统")
|
||
browser: str = Field(..., description="浏览器")
|
||
uri: str = Field(..., description="访问路径")
|
||
title: str = Field(None, description="博客标题")
|
||
visit_time: datetime = Field(..., description="访问时间", alias="visitTime")
|
||
|
||
model_config = ConfigDict(
|
||
from_attributes=True,
|
||
populate_by_name=True,
|
||
json_encoders={
|
||
datetime: lambda dt: dt.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
)
|
||
|
||
|
||
class BlogLatestResponse(BaseModel):
|
||
id: int = Field(..., description="博客ID")
|
||
title: str = Field(..., description="博客标题")
|
||
|
||
model_config = ConfigDict(
|
||
from_attributes=True,
|
||
populate_by_name=True
|
||
)
|
||
|
||
|
||
class BlogAdjacentResponse(BaseModel):
|
||
id: int = Field(..., description="博客ID")
|
||
title: str = Field(..., description="博客标题")
|
||
|
||
model_config = ConfigDict(
|
||
from_attributes=True,
|
||
populate_by_name=True
|
||
)
|
||
|
||
|
||
class BlogCommentCreate(BaseModel):
|
||
parent_id: int = Field(default=0, ge=0, description="父评论ID,0表示顶级评论", alias="parentId")
|
||
name: str = Field(..., min_length=1, max_length=50, description="评论人昵称")
|
||
website: Optional[str] = Field(None, description="评论人网站")
|
||
content: str = Field(..., min_length=1, max_length=1000, description="评论内容")
|
||
|
||
@field_validator('name')
|
||
def name_not_empty(cls, v):
|
||
if not v or not v.strip():
|
||
raise ValueError('昵称不能为空')
|
||
return v.strip()
|
||
|
||
@field_validator('content')
|
||
def content_not_empty(cls, v):
|
||
if not v or not v.strip():
|
||
raise ValueError('评论内容不能为空')
|
||
return v.strip()
|
||
|
||
|
||
class BlogCommentResponse(BlogCommentCreate):
|
||
id: int = Field(..., description="评论ID")
|
||
ip_address: str = Field(..., description="IP地址", alias="ipAddress")
|
||
user_agent: str = Field(..., description="浏览器信息", alias="userAgent")
|
||
create_time: datetime = Field(..., description="创建时间", alias="createTime")
|
||
|
||
model_config = ConfigDict(
|
||
from_attributes=True,
|
||
populate_by_name=True,
|
||
json_encoders={
|
||
datetime: lambda dt: dt.strftime('%Y-%m-%d %H:%M:%S')
|
||
}
|
||
)
|