113 lines
3.7 KiB
Python
113 lines
3.7 KiB
Python
|
|
from django.core.paginator import Paginator
|
|||
|
|
from django.http import JsonResponse
|
|||
|
|
|
|||
|
|
from django.core.exceptions import ValidationError
|
|||
|
|
from django.utils.html import escape
|
|||
|
|
from .models import Article
|
|||
|
|
from django.shortcuts import get_object_or_404
|
|||
|
|
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
|||
|
|
|
|||
|
|
# 文章列表页视图,带分页和请求频率限制
|
|||
|
|
def article_list(request):
|
|||
|
|
|
|||
|
|
# 获取分页参数
|
|||
|
|
page = request.GET.get('page', 1) # 当前页数,默认为第一页
|
|||
|
|
limit = request.GET.get('limit', 10) # 每页文章数,默认为10
|
|||
|
|
|
|||
|
|
# 获取所有文章,并按发布时间倒序排序
|
|||
|
|
articles = Article.objects.all().order_by('-published_at')
|
|||
|
|
|
|||
|
|
# 使用 Paginator 进行分页
|
|||
|
|
paginator = Paginator(articles, limit)
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
current_page = paginator.page(page) # 获取当前页的数据
|
|||
|
|
except PageNotAnInteger:
|
|||
|
|
current_page = paginator.page(1) # 如果请求的页数不存在,默认返回第一页
|
|||
|
|
except EmptyPage:
|
|||
|
|
# 如果页码超出范围,返回空列表
|
|||
|
|
return JsonResponse({'code': 200, 'message': '没有更多数据', 'data': {}})
|
|||
|
|
|
|||
|
|
# 将文章列表转换为字典列表
|
|||
|
|
articles_list = list(current_page.object_list.values('id', 'chinese_title', 'english_title', 'published_at', 'status'))
|
|||
|
|
|
|||
|
|
# 格式化文章的发布时间
|
|||
|
|
for article in articles_list:
|
|||
|
|
article['published_at'] = article['published_at'].strftime('%Y-%m-%d %H:%M:%S') if article['published_at'] else '未发布'
|
|||
|
|
|
|||
|
|
# 返回 JSON 数据,适配前端使用
|
|||
|
|
data = {
|
|||
|
|
"code": 200,
|
|||
|
|
"msg": "成功",
|
|||
|
|
"count": paginator.count, # 文章总数
|
|||
|
|
"data": articles_list
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
return JsonResponse(data)
|
|||
|
|
|
|||
|
|
def article_detail(request, pk, lang):
|
|||
|
|
try:
|
|||
|
|
# 检查是否传入了危险参数 (如防止SQL注入等)
|
|||
|
|
pk = escape(pk) # 对传入的主键进行转义,避免潜在的注入风险
|
|||
|
|
lang = escape(lang) # 对语言参数进行转义
|
|||
|
|
|
|||
|
|
# 检查参数是否有效
|
|||
|
|
if not pk or not lang:
|
|||
|
|
raise ValidationError('参数不能为空')
|
|||
|
|
|
|||
|
|
# 检查语言是否有效
|
|||
|
|
if lang not in ['zh', 'en']:
|
|||
|
|
return JsonResponse({
|
|||
|
|
"code": 400,
|
|||
|
|
"msg": "无效的语言参数",
|
|||
|
|
"data": {}
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
# 获取指定的文章
|
|||
|
|
article = get_object_or_404(Article, pk=pk)
|
|||
|
|
|
|||
|
|
# 根据语言参数返回不同语言的文章内容
|
|||
|
|
if lang == 'en':
|
|||
|
|
title = article.english_title
|
|||
|
|
keywords = article.english_keywords
|
|||
|
|
content = article.english_content
|
|||
|
|
else:
|
|||
|
|
title = article.chinese_title
|
|||
|
|
keywords = article.chinese_keywords
|
|||
|
|
content = article.chinese_content
|
|||
|
|
|
|||
|
|
# 构造响应数据
|
|||
|
|
data = {
|
|||
|
|
"code": 200,
|
|||
|
|
"msg": "成功",
|
|||
|
|
"data": {
|
|||
|
|
'id': article.id,
|
|||
|
|
'title': title,
|
|||
|
|
'keywords': keywords,
|
|||
|
|
'content': content,
|
|||
|
|
'published_at': article.published_at.strftime('%Y-%m-%d %H:%M:%S') if article.published_at else '未发布',
|
|||
|
|
'status': article.status
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
return JsonResponse(data)
|
|||
|
|
|
|||
|
|
except ValidationError as ve:
|
|||
|
|
return JsonResponse({
|
|||
|
|
"code": 400,
|
|||
|
|
"msg": str(ve),
|
|||
|
|
"data": {}
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
except Article.DoesNotExist:
|
|||
|
|
return JsonResponse({
|
|||
|
|
"code": 404,
|
|||
|
|
"msg": "未找到对应的文章",
|
|||
|
|
"data": {}
|
|||
|
|
})
|
|||
|
|
|
|||
|
|
except Exception as e:
|
|||
|
|
return JsonResponse({
|
|||
|
|
"code": 500,
|
|||
|
|
"msg": "服务器内部错误",
|
|||
|
|
"data": {"error": str(e)}
|
|||
|
|
})
|