You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DjangoBlog/blog/views.py

398 lines
14 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

from django.shortcuts import render, get_object_or_404, redirect
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Q
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from django.http import JsonResponse
from django.views.decorators.http import require_POST
from .models import Post, Category
from .forms import PostForm
from comments.forms import CommentForm # 从comments应用导入CommentForm
def index(request):
"""首页视图 - 显示最新发布的文章"""
# LXC获取所有已发布的文章按照创建时间倒序排列
post_list_all = Post.objects.filter(status='published').order_by('-created_time')
# LXC创建分页器对象每页显示10篇文章
paginator = Paginator(post_list_all, 10)
page_number = request.GET.get('page')
try:
post_list = paginator.page(page_number)
except PageNotAnInteger:
# LXC当页码不是整数时显示第一页内容
post_list = paginator.page(1)
except EmptyPage:
# LXC当页码超出范围时显示最后一页内容
post_list = paginator.page(paginator.num_pages)
# LXC获取热门文章按浏览量降序排列取前5篇
hot_posts = Post.objects.filter(status='published').order_by('-views')[:5]
# LXC构建页面上下文数据
context = {
'post_list': post_list,
'hot_posts': hot_posts,
'category_info': {
'name': '非遗传承',
'label': '',
'desc': '探索南京非物质文化遗产的独特魅力与传承故事'
},
'current_path': request.path,
'current_category_id': None
}
# LXC渲染首页模板并返回响应
return render(request, 'blog/index.html', context)
def category_view(request, category_id):
"""分类页面视图 - 显示指定分类的文章"""
# LXC根据分类ID获取分类对象如果不存在则返回404错误
category = get_object_or_404(Category, id=category_id)
# LXC获取该分类下所有已发布的文章按创建时间倒序排列
posts_all = Post.objects.filter(category=category, status='published').order_by('-created_time')
# LXC创建分页器对象每页显示10篇文章
paginator = Paginator(posts_all, 10)
page_number = request.GET.get('page')
try:
posts = paginator.page(page_number)
except PageNotAnInteger:
posts = paginator.page(1)
except EmptyPage:
posts = paginator.page(paginator.num_pages)
# LXC获取热门文章按浏览量降序排列取前5篇
hot_posts = Post.objects.filter(status='published').order_by('-views')[:5]
# LXC定义分类信息映射字典包含每个分类的显示标签和描述
category_map = {
1: {'label': '巧夺天工·工艺', 'desc': '探索南京传统手工艺的精湛技艺与匠心传承'},
2: {'label': '梨园雅韵·表演', 'desc': '感受南京传统表演艺术的独特韵味与舞台魅力'},
3: {'label': '人间烟火·民俗', 'desc': '体验南京丰富多彩的民俗活动与民间传统'},
4: {'label': '口传心授·文学', 'desc': '领略南京口传文学的语言艺术与文化内涵'},
5: {'label': '匠心传承·人物', 'desc': '认识南京非物质文化遗产的传承人与守护者'},
}
# LXC根据分类ID获取对应的分类信息如果不存在则使用默认值
category_info = category_map.get(category_id, {
'label': category.name,
'desc': f'探索南京{category.name}的独特魅力'
})
# LXC构建页面上下文数据
context = {
'post_list': posts,
'hot_posts': hot_posts,
'category_info': {
'name': category.name,
'label': category_info['label'],
'desc': category_info['desc']
},
'current_path': request.path,
'current_category_id': category_id
}
# LXC渲染分类页面模板并返回响应
return render(request, 'blog/index.html', context)
def detail(request, post_id):
"""文章详情页 - 显示单篇文章的完整内容"""
# LXC根据文章ID获取已发布的文章对象如果不存在则返回404错误
post = get_object_or_404(Post, id=post_id, status='published')
# LXC增加文章浏览量并保存到数据库
post.views += 1
post.save()
# LXC导入评论模型
from comments.models import Comment
# LXC获取该文章的所有评论按创建时间倒序排列
comments = post.comments.all().order_by('-created_time')
# LXC创建评论表单实例
comment_form = CommentForm()
# LXC构建页面上下文数据
context = {
'post': post,
'comments': comments,
'comment_form': comment_form,
}
# LXC渲染文章详情页模板并返回响应
return render(request, 'blog/detail.html', context)
def search(request):
"""搜索文章 - 根据关键词搜索文章内容"""
# LXC获取搜索关键词并去除首尾空格
query = request.GET.get('q', '').strip()
# LXC获取热门文章按浏览量降序排列取前5篇
hot_posts = Post.objects.filter(status='published').order_by('-views')[:5]
# LXC初始化空的搜索结果集
results = Post.objects.none()
result_count = 0
if query:
# LXC如果有关键词执行多字段搜索
results = Post.objects.filter(
Q(title__icontains=query) |
Q(content__icontains=query) |
Q(excerpt__icontains=query) |
Q(primary_tags__name__icontains=query) |
Q(secondary_tags__name__icontains=query),
status='published'
).distinct().order_by('-created_time')
# LXC统计搜索结果数量
result_count = results.count()
# LXC如果没有搜索结果添加提示消息
if result_count == 0:
messages.info(request, f'没有找到包含"{query}"的文章,请尝试其他关键词。')
else:
# LXC如果没有输入关键词显示提示信息
messages.info(request, '请输入搜索关键词。')
# LXC创建分页器对象每页显示10篇文章
paginator = Paginator(results, 10)
page_number = request.GET.get('page')
try:
page_obj = paginator.page(page_number)
except PageNotAnInteger:
page_obj = paginator.page(1)
except EmptyPage:
page_obj = paginator.page(paginator.num_pages)
# LXC构建页面上下文数据
context = {
'post_list': page_obj,
'hot_posts': hot_posts,
'category_info': {
'name': f'搜索"{query}"' if query else '搜索',
'label': '搜索结果',
'desc': f'找到 {result_count} 篇相关文章' if query else '请输入搜索关键词'
},
'current_path': request.path,
'current_category_id': None,
'search_query': query
}
return render(request, 'blog/index.html', context)
def about(request):
"""关于页面 - 网站介绍"""
context = {
'category_info': {
'name': '关于我们',
'label': '关于金陵非遗',
'desc': '了解南京非物质文化遗产保护与传承的使命'
},
'current_path': request.path,
}
return render(request, 'blog/about.html', context)
# ========== 文章管理视图函数 ==========
@login_required
def create_post(request):
"""发表新文章"""
if request.method == 'POST':
# LXC使用POST数据和文件数据初始化表单
form = PostForm(request.POST, request.FILES)
if form.is_valid():
# LXC保存文章但不提交到数据库以便设置作者
post = form.save(commit=False)
# LXC设置文章作者为当前登录用户
post.author = request.user
# LXC新文章默认为草稿状态
post.status = 'draft'
post.save()
# LXC保存多对多关系标签
form.save_m2m()
messages.success(request, '文章创建成功!已保存为草稿。')
return redirect('user_posts')
else:
messages.error(request, '文章创建失败,请检查表单内容。')
else:
# LXCGET请求时创建空表单
form = PostForm()
context = {
'form': form,
'category_info': {
'name': '发表文章',
'label': '创作非遗',
'desc': '分享您对南京非物质文化遗产的见解和故事'
},
'current_path': request.path,
}
return render(request, 'blog/create_post.html', context)
@login_required
def user_posts(request):
"""用户个人文章管理"""
# LXC获取当前用户的所有文章按创建时间倒序排列
posts = Post.objects.filter(author=request.user).order_by('-created_time')
context = {
'posts': posts,
'category_info': {
'name': '我的文章',
'label': '个人创作',
'desc': '管理您发表的非遗文章'
},
'current_path': request.path,
}
return render(request, 'blog/user_posts.html', context)
@login_required
def edit_post(request, post_id):
"""编辑文章"""
# LXC获取文章对象确保作者是当前用户
post = get_object_or_404(Post, id=post_id, author=request.user)
if request.method == 'POST':
# LXC使用POST数据和文件数据初始化表单并绑定到现有文章实例
form = PostForm(request.POST, request.FILES, instance=post)
if form.is_valid():
form.save()
messages.success(request, '文章更新成功!')
return redirect('user_posts')
else:
messages.error(request, '文章更新失败,请检查表单内容。')
else:
# LXCGET请求时使用现有文章数据初始化表单
form = PostForm(instance=post)
context = {
'form': form,
'post': post,
'category_info': {
'name': '编辑文章',
'label': '修改创作',
'desc': '修改您的非遗文章内容'
},
'current_path': request.path,
}
return render(request, 'blog/edit_post.html', context)
@login_required
@require_POST
def publish_post(request, post_id):
"""发布文章(将草稿状态改为已发布)"""
# LXC获取文章对象确保作者是当前用户
post = get_object_or_404(Post, id=post_id, author=request.user)
if post.status == 'draft':
# LXC将文章状态从草稿改为已发布
post.status = 'published'
post.save()
messages.success(request, '文章已成功发布!')
else:
messages.warning(request, '文章状态未改变。')
return redirect('user_posts')
@login_required
@require_POST
def delete_post(request, post_id):
"""删除文章"""
# LXC获取文章对象确保作者是当前用户
post = get_object_or_404(Post, id=post_id, author=request.user)
post_title = post.title
# LXC删除文章
post.delete()
messages.success(request, f'文章 "{post_title}" 已删除。')
return redirect('user_posts')
@login_required
@require_POST
def like_post(request, post_id):
"""点赞文章"""
# LXC获取文章对象
post = get_object_or_404(Post, id=post_id)
# LXC实现点赞功能逻辑
if post.likes.filter(id=request.user.id).exists():
# LXC如果已经点赞取消点赞
post.likes.remove(request.user)
liked = False
else:
# LXC如果没有点赞添加点赞
post.likes.add(request.user)
liked = True
# LXC返回JSON响应包含点赞状态和点赞数量
return JsonResponse({
'liked': liked,
'likes_count': post.likes.count()
})
@login_required
@require_POST
def favorite_post(request, post_id):
"""收藏文章"""
# LXC获取文章对象
post = get_object_or_404(Post, id=post_id)
# LXC实现收藏功能逻辑
if post.favorites.filter(id=request.user.id).exists():
# LXC如果已经收藏取消收藏
post.favorites.remove(request.user)
favorited = False
else:
# LXC如果没有收藏添加收藏
post.favorites.add(request.user)
favorited = True
# LXC返回JSON响应包含收藏状态和收藏数量
return JsonResponse({
'favorited': favorited,
'favorites_count': post.favorites.count()
})
@login_required
def edit_post(request, post_id):
"""编辑文章"""
try:
# LXC获取文章对象确保作者是当前用户否则重定向
post = get_object_or_404(Post, id=post_id, author=request.user)
except:
messages.error(request, '您没有权限编辑这篇文章或文章不存在。')
return redirect('user_posts')
if request.method == 'POST':
# LXC使用POST数据和文件数据初始化表单并绑定到现有文章实例
form = PostForm(request.POST, request.FILES, instance=post)
if form.is_valid():
form.save()
messages.success(request, '文章更新成功!')
return redirect('user_posts')
else:
messages.error(request, '文章更新失败,请检查表单内容。')
else:
# LXCGET请求时使用现有文章数据初始化表单
form = PostForm(instance=post)
context = {
'form': form,
'post': post,
'category_info': {
'name': '编辑文章',
'label': '修改创作',
'desc': '修改您的非遗文章内容'
},
'current_path': request.path,
}
return render(request, 'blog/edit_post.html', context)