update. 更新文章接口
This commit is contained in:
+31
-30
@@ -2,7 +2,6 @@ from datetime import datetime
|
|||||||
from typing import Optional, List, Generic, T
|
from typing import Optional, List, Generic, T
|
||||||
|
|
||||||
from ninja import Schema
|
from ninja import Schema
|
||||||
from pydantic import Field
|
|
||||||
|
|
||||||
|
|
||||||
# --- 假设的关联模型 Schema ---
|
# --- 假设的关联模型 Schema ---
|
||||||
@@ -16,47 +15,49 @@ class SectionSchema(Schema):
|
|||||||
title: str # 假设 MainMenu 有 name 字段
|
title: str # 假设 MainMenu 有 name 字段
|
||||||
|
|
||||||
|
|
||||||
class AttachmentSchema(Schema):
|
class ArticleAttachmentOut(Schema):
|
||||||
id: int
|
id: int
|
||||||
file: str # 返回文件 URL 路径,如 "articles/attachments/2026/04/03/file.pdf"
|
file: str
|
||||||
|
|
||||||
|
|
||||||
class PaginatedResponseSchema(Schema, Generic[T]):
|
class ArticleListOut(Schema):
|
||||||
items: List[T]
|
|
||||||
total: int
|
|
||||||
page: int
|
|
||||||
per_page: int
|
|
||||||
total_pages: int
|
|
||||||
|
|
||||||
|
|
||||||
# --- Article 主 Schema ---
|
|
||||||
class ArticleSchema(Schema):
|
|
||||||
id: int
|
id: int
|
||||||
title: str
|
title: str
|
||||||
content: str
|
|
||||||
cover: Optional[str] = None # 图片 URL 路径
|
section: SectionSchema
|
||||||
|
|
||||||
|
author: AuthorSchema
|
||||||
|
|
||||||
|
cover: Optional[str] = None
|
||||||
is_contribution: bool
|
is_contribution: bool
|
||||||
is_published: bool
|
is_published: bool
|
||||||
created_at: datetime
|
|
||||||
updated_at: datetime
|
|
||||||
|
|
||||||
# 关联字段
|
|
||||||
author: Optional[AuthorSchema] = None
|
|
||||||
section: Optional[SectionSchema] = None
|
|
||||||
attachments: List[AttachmentSchema] = Field(default_factory=list)
|
|
||||||
|
|
||||||
|
|
||||||
# --- 创建文章用的 Schema (不含只读字段) ---
|
class ArticleDetailOut(Schema):
|
||||||
class ArticleCreateSchema(Schema):
|
id: int
|
||||||
title: str
|
title: str
|
||||||
section_id: Optional[int] = None # 外键通过 ID 传递
|
|
||||||
|
section: SectionSchema
|
||||||
|
|
||||||
|
author: AuthorSchema
|
||||||
|
|
||||||
|
content: str
|
||||||
|
cover: Optional[str] = None
|
||||||
|
|
||||||
|
is_contribution: bool
|
||||||
|
is_published: bool
|
||||||
|
|
||||||
|
attachments: List[ArticleAttachmentOut] = []
|
||||||
|
|
||||||
|
|
||||||
|
class ArticleCreate(Schema):
|
||||||
|
title: str
|
||||||
|
section_id: Optional[int] = None
|
||||||
|
author_id: Optional[int] = None
|
||||||
content: str
|
content: str
|
||||||
cover: Optional[str] = None # 注意:文件上传通常需单独处理,此处仅为文本路径示例
|
|
||||||
is_contribution: bool = False
|
is_contribution: bool = False
|
||||||
is_published: bool = True
|
is_published: bool = True
|
||||||
|
|
||||||
|
|
||||||
# --- 更新文章用的 Schema ---
|
class ArticleUpdate(ArticleCreate):
|
||||||
class ArticleUpdateSchema(ArticleCreateSchema):
|
pass
|
||||||
title: Optional[str] = None
|
|
||||||
content: Optional[str] = None
|
|
||||||
|
|||||||
+35
-19
@@ -1,34 +1,50 @@
|
|||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
|
from django.shortcuts import get_object_or_404
|
||||||
from ninja import Router
|
from ninja import Router
|
||||||
from ninja.pagination import paginate, PageNumberPagination
|
from ninja.pagination import paginate, PageNumberPagination
|
||||||
|
|
||||||
from article.models import Article
|
from article.models import Article
|
||||||
from article.schema import ArticleSchema, ArticleCreateSchema
|
from article.schema import ArticleUpdate, ArticleCreate, ArticleListOut, ArticleDetailOut
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
router = Router(tags=['content'])
|
router = Router(tags=['Article'])
|
||||||
|
|
||||||
|
|
||||||
@router.get("/article", response=List[ArticleSchema], description="获取文章列表")
|
@router.get("/article/", response=List[ArticleListOut], description="获取文章列表")
|
||||||
@paginate(PageNumberPagination, page_size=50)
|
@paginate(PageNumberPagination, page_size=20)
|
||||||
def list_articles(request, ):
|
def list_articles(request, title: str = '', section_id: int = 0):
|
||||||
# 安全校验 per_page(防止过大
|
qs = (Article.objects.filter(title__contains=title).prefetch_related('attachments')
|
||||||
queryset = Article.objects.prefetch_related('attachments').select_related('author', 'section')
|
.select_related('author', 'section').order_by("-id"))
|
||||||
return queryset
|
if section_id > 0:
|
||||||
|
return qs.filter(section_id=section_id)
|
||||||
|
return qs
|
||||||
|
|
||||||
|
|
||||||
@router.post("/article", response=ArticleSchema)
|
@router.get("/article/{id}", response=ArticleDetailOut)
|
||||||
def create_article(request, payload: ArticleCreateSchema):
|
def get_article(request, id: int):
|
||||||
# 注意:文件上传需额外处理(此处简化)
|
return get_object_or_404(Article.objects.prefetch_related("attachments"), id=id)
|
||||||
article = Article.objects.create(
|
|
||||||
title=payload.title,
|
|
||||||
section_id=payload.section_id,
|
@router.post("/article/", response=ArticleDetailOut)
|
||||||
author=request.auth, # 假设认证用户是作者
|
def create_article(request, data: ArticleCreate):
|
||||||
content=payload.content,
|
article = Article.objects.create(**data.dict())
|
||||||
is_contribution=payload.is_contribution,
|
|
||||||
is_published=payload.is_published,
|
|
||||||
)
|
|
||||||
return article
|
return article
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/article/{id}", response=ArticleDetailOut)
|
||||||
|
def update_article(request, id: int, data: ArticleUpdate):
|
||||||
|
article = get_object_or_404(Article, id=id)
|
||||||
|
for attr, value in data.dict().items():
|
||||||
|
setattr(article, attr, value)
|
||||||
|
article.save()
|
||||||
|
return article
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/article/{id}")
|
||||||
|
def delete_article(request, id: int):
|
||||||
|
article = get_object_or_404(Article, id=id)
|
||||||
|
article.delete()
|
||||||
|
return {"success": True}
|
||||||
|
|||||||
Reference in New Issue
Block a user