留言板模块包括读者留言和管理员回复,屏蔽或删除留言。
- 读者留言按时间倒序排列。
- 管理员回复的留言在每条读者留言的下方。
- 管理员可以对评论进行回复,屏蔽或删除某条留言。
首先构造留言板的模型。
#comment 模块 models.py
from django.db import models
from user.models import MyUser
class Message(models.Model):
msgid = models.AutoField('序号', primary_key=True)
content = models.TextField('留言内容', )
date = models.DateField('留言时间',)
from_user = models.ForeignKey(MyUser, on_delete=models.CASCADE, verbose_name='留言者')
msg_status= models.IntegerField('留言状态', default=1)
parent_msgid = models.ForeignKey('self', verbose_name="回复留言", on_delete=models.CASCADE, blank=True, null=True)
def __str__(self):
return self.content
class Meta:
verbose_name = '用户留言'
verbose_name_plural = '用户留言'
上面的字段中,msg_status用来表示是否显示用户的留言,默认为1表示显示留言,parent_msgid外键关联自身的msgid,表示是对关联的留言的回复留言。其他的字段很好理解。模型建好以后执行数据迁移,创建好数据表。
然后到项目的urls.py中开启最后一道大门。
下面就是编写comment应用的URL地址信息和视图函数,以及在templates下添加message.html模板文件
# comment 下的 urls.py
from django.urls import path
from . import views
#设置URL的地址信息
urlpatterns = [
path('message/', views.messageView, name='message'),
]
#comment 下的 views.py
from django.shortcuts import render
from .models import Message
from user.models import Library, MyUser
from datetime import datetime
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.contrib.auth.decorators import login_required
@login_required(login_url='/user/login.html')
def messageView(request, page):
#获取该用户所属馆的馆名和馆实例对象
lib_name = request.user.lib_id
library = Library.objects.get(lib_name=lib_name)
#如果是POST请求,则说明用户在发表留言
if request.method == 'POST':
user_id = MyUser.objects.get(id=request.user.id)
time = datetime.now()
content = request.POST.get('content')
Message.objects.create(content=content, date=time, from_user=user_id)
#查询所在馆的留言记录倒序排列
messages = Message.objects.select_related('from_user__lib_id').filter(from_user__lib_id__lib_id=library.lib_id).order_by('-msgid')
#分页
paginator = Paginator(messages, 5)
try:
pageInfo = paginator.page(page)
except PageNotAnInteger:
pageInfo = paginator.page(1)
except EmptyPage:
pageInfo = paginator.page(paginator.num_pages)
return render(request, 'message.html', locals())
简单的讲解一下逻辑,接收到用户请求后,首先获取图书馆馆名和馆的实例对象,然后判断是不是POST请求,如果是则说明用户在发表留言,将留言相关信息保存到数据库,如果是GET请求,获取该用户所在图书馆的所有留言记录并且倒序排列,输出到模板文件message.html。最后看下模板文件。
{% extends "base.html" %}
{% load staticfiles %}
{# 隐藏顶部搜索框 #}
{% block search %}
{% endblock %}
{% block body %}
{{ lib_name }}-留言板
{% for msg in pageInfo %}
{% if msg.parent_msgid == NULL %}
由 {{ msg.from_user }} {{ msg.date }} 留言
- {{ msg.content }}
{% else %}
由 {{ msg.parent_msgid.from_user }} {{ msg.parent_msgid.date }} 留言
- {{ msg.parent_msgid.content }}
由 {{ msg.from_user }} {{ msg.date }} 回复
- {{ msg.content }}
{% endif %}
{% endfor %}
{# 分页 #}
{% endblock %}
实现效果如下:
然后就是做个留言板后台管理模块,在library应用里添加新的URL地址信息
path('lib_msgadmin//', views.LibMsgAdminView, name='lib_msgadmin'),
编写留言板后台管理的视图函数LibMsgAdminView,别忘记头部导入相关模块和模型,这里只贴出了部分代码。
#登陆验证和身份验证
@login_required(login_url='/user/login.html')
@permission_required(perm='recommend.change_recommend')
#图书馆留言管理
def LibMsgAdminView(request, page):
#获取该用户所属馆名
lib_name = request.user.lib_id
#获取该馆实例对象
library = Library.objects.get(lib_name=lib_name)
#如果是POST请求,则说明是管理员在回复用户留言
if request.method == 'POST':
#获取用户的实例对象
myuser = MyUser.objects.get(id=request.user.id)
#通过隐藏表单获取用户留言的msgid
msgid=request.POST.get('msgid')
#转为msg的实例对象
msginstance = Message.objects.get(msgid=msgid)
content = request.POST.get('content')
time = datetime.now()
Message.objects.create(content=content, date=time, from_user=myuser, parent_msgid=msginstance)
#查询所在馆的留言记录倒序排列
messages = Message.objects.select_related('from_user__lib_id').filter(from_user__lib_id__lib_id=library.lib_id).order_by('-msgid')
#分页
paginator = Paginator(messages, 5)
try:
pageInfo = paginator.page(page)
except PageNotAnInteger:
pageInfo = paginator.page(1)
except EmptyPage:
pageInfo = paginator.page(paginator.num_pages)
return render(request, 'lib_msgadmin.html', locals())
后台管理的逻辑和前台差不多,主要差别就是回复留言的时候获取了隐藏表单中用户留言的msgid保存到数据表中的parent_id外键中。
模板文件lib_msgadmin.html如下:
{% extends "base.html" %}
{% load staticfiles %}
{# 隐藏顶部搜索框 #}
{% block search %}
{% endblock %}
{% block body %}
{{ lib_name }}-留言板管理
{% for msg in pageInfo %}
{% if msg.parent_msgid == NULL %}
由 {{ msg.from_user }} {{ msg.date }} 留言
- {{ msg.content }}
{% else %}
由 {{ msg.parent_msgid.from_user }} {{ msg.parent_msgid.date }} 留言
- {{ msg.parent_msgid.content }}
由 {{ msg.from_user }} {{ msg.date }} 回复
- {{ msg.content }}
{% endif %}
{% endfor %}
{# 分页 #}
{% endblock %}
回复留言
回复后的效果
留言板里的效果
如果需要对留言板有一个控制,比如能够屏蔽某些非法留言,就可以用到msg_status这个字段,数据表中默认是 1,我们把它该成非1的值就能实现屏蔽留言的功能。
首先到浏览展示的模板文件message.html中添加一个条件判断。
{% if msg.msg_status == 1 %}
然后在留言板管理后台模板lib_msgadmin.html添加一个屏蔽留言的功能按钮
{% if msg.msg_status == 1 %}
{% else %}
{% endif %}
模板将浏览的msgid通过GET参数传递给视图函数处理。
视图函数中多做一个If判断,将GET获取到的msgid的msg_status设置为0或任意其他值即可实现留言的屏蔽。
#如果通过GET获取到了msgid,说明是管理员用户要屏蔽该条留言
if request.GET.get('msgid'):
msgid = request.GET.get('msgid')
#将留言状态设置为0
Message.objects.filter(msgid=msgid).update(msg_status=0)
点击屏蔽按钮后,该条留言成为已屏蔽状态,进入留言板模板可以发现被屏蔽的留言不见了。
但是,我们发现留言被屏蔽了2条,现在第一页只有3条留言了,被屏蔽的留言虽然没有显示,但还是被从数据库中读取出来了,这种情况,我们只要在查询数据的时候再加 msg_status=1 这个条件,这样读取的就全是正常状态的留言了。
#comment 的 views.py
messages = Message.objects.select_related('from_user__lib_id').filter(from_user__lib_id__lib_id=library.lib_id,msg_status=1).order_by('-msgid')
现在再看留言板,第一页就是完整的5条留言了。