Django圖書薦購云平臺(tái)開發(fā)與實(shí)踐 - 6留言板模塊

留言板模塊包括讀者留言和管理員回復(fù),屏蔽或刪除留言。

  1. 讀者留言按時(shí)間倒序排列。
  2. 管理員回復(fù)的留言在每條讀者留言的下方。
  3. 管理員可以對(duì)評(píng)論進(jìn)行回復(fù),屏蔽或刪除某條留言。

首先構(gòu)造留言板的模型。

#comment 模塊 models.py
from django.db import models
from user.models import MyUser

class Message(models.Model):
    msgid = models.AutoField('序號(hào)', primary_key=True)
    content = models.TextField('留言內(nèi)容', )
    date = models.DateField('留言時(shí)間',)
    from_user = models.ForeignKey(MyUser, on_delete=models.CASCADE, verbose_name='留言者')
    msg_status= models.IntegerField('留言狀態(tài)', default=1)
    parent_msgid =  models.ForeignKey('self', verbose_name="回復(fù)留言", on_delete=models.CASCADE, blank=True, null=True)
    def __str__(self):
        return self.content

    class Meta:
        verbose_name = '用戶留言'
        verbose_name_plural = '用戶留言'

上面的字段中,msg_status用來表示是否顯示用戶的留言,默認(rèn)為1表示顯示留言,parent_msgid外鍵關(guān)聯(lián)自身的msgid,表示是對(duì)關(guān)聯(lián)的留言的回復(fù)留言。其他的字段很好理解。模型建好以后執(zhí)行數(shù)據(jù)遷移,創(chuàng)建好數(shù)據(jù)表。
然后到項(xiàng)目的urls.py中開啟最后一道大門
下面就是編寫comment應(yīng)用的URL地址信息和視圖函數(shù),以及在templates下添加message.html模板文件

# comment 下的 urls.py
from django.urls import path
from . import views

#設(shè)置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):
    #獲取該用戶所屬館的館名和館實(shí)例對(duì)象
    lib_name = request.user.lib_id
    library = Library.objects.get(lib_name=lib_name)
 
    #如果是POST請(qǐng)求,則說明用戶在發(fā)表留言
    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())

簡(jiǎn)單的講解一下邏輯,接收到用戶請(qǐng)求后,首先獲取圖書館館名和館的實(shí)例對(duì)象,然后判斷是不是POST請(qǐng)求,如果是則說明用戶在發(fā)表留言,將留言相關(guān)信息保存到數(shù)據(jù)庫,如果是GET請(qǐng)求,獲取該用戶所在圖書館的所有留言記錄并且倒序排列,輸出到模板文件message.html。最后看下模板文件。

{% extends "base.html" %}
{% load staticfiles %}
<link rel="stylesheet" href="{% static 'css/mycss.css' %}">
{# 隱藏頂部搜索框 #}
{% block search %}
{% endblock %}
{% block body %}
<div class="alert alert-success mx-auto">
    <span><h5>{{ lib_name }}-留言板</h5></span>
</div>

<ul class="list-group">
    {% for msg in pageInfo %}
        {% if msg.parent_msgid == NULL %}
        <div class="alert alert-info">
            <lable>由 <strong>{{ msg.from_user }}</strong>&nbsp;&nbsp;<small>{{ msg.date }} </small>留言</lable>
            <li class="list-group-item">{{ msg.content }}</li>
        </div>
        {% else %}
        <div class="alert alert-info">
            <lable>由 <strong>{{ msg.parent_msgid.from_user }}</strong>&nbsp;&nbsp;<small>{{ msg.parent_msgid.date }} </small>留言
            <li class="list-group-item">{{ msg.parent_msgid.content }}</li>
        </div>
        <div class="alert alert-warning">
            <div class="clearfix">
                <div class="float-right">
                    <lable>由 <strong>{{ msg.from_user }}</strong>&nbsp;&nbsp;<small>{{ msg.date }} </small>回復(fù)</lable>  
                </div>
            </div>
            <li class="list-group-item">{{ msg.content }}</li>   
        </div>

        {% endif %}
    {% endfor %}
</ul>

{# 分頁 #}
<div class="center">
<ul class="pagination">
    {% if pageInfo.has_previous %}
    <li class="page-item"><a class="page-link" href="{% url 'message' pageInfo.previous_page_number %}">上一頁</a></li>
    {% endif %}
    {% if pageInfo.has_next %}
    <li class="page-item"><a class="page-link" href="{% url 'message' pageInfo.next_page_number %}">下一頁</a></li>
    {% endif %}
</ul>
</div>

<form  action="{% url 'message' 1 %}" method="POST">
    {% csrf_token %}
    <div class="form-group alert alert-info col-sm-12">
        <label for="comment">用戶名:<strong>{{ user.username }}</strong></label>
        <textarea class="form-control" rows="5" name="content" id="comment" placeholder="請(qǐng)留言..." required></textarea>    
        <button type="submit" class="btn btn-primary">留言</button>
    </div>
</form>
{% endblock %}

實(shí)現(xiàn)效果如下:


image.png

然后就是做個(gè)留言板后臺(tái)管理模塊,在library應(yīng)用里添加新的URL地址信息

    path('lib_msgadmin/<int:page>/', views.LibMsgAdminView, name='lib_msgadmin'),

編寫留言板后臺(tái)管理的視圖函數(shù)LibMsgAdminView,別忘記頭部導(dǎo)入相關(guān)模塊和模型,這里只貼出了部分代碼。

#登陸驗(yàn)證和身份驗(yàn)證
@login_required(login_url='/user/login.html')
@permission_required(perm='recommend.change_recommend')
#圖書館留言管理
def LibMsgAdminView(request, page):
    #獲取該用戶所屬館名
    lib_name = request.user.lib_id
    #獲取該館實(shí)例對(duì)象
    library = Library.objects.get(lib_name=lib_name)
    #如果是POST請(qǐng)求,則說明是管理員在回復(fù)用戶留言
    if request.method == 'POST':
        #獲取用戶的實(shí)例對(duì)象
        myuser = MyUser.objects.get(id=request.user.id)
        #通過隱藏表單獲取用戶留言的msgid
        msgid=request.POST.get('msgid')
        #轉(zhuǎn)為msg的實(shí)例對(duì)象
        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())

后臺(tái)管理的邏輯和前臺(tái)差不多,主要差別就是回復(fù)留言的時(shí)候獲取了隱藏表單中用戶留言的msgid保存到數(shù)據(jù)表中的parent_id外鍵中。
模板文件lib_msgadmin.html如下:

{% extends "base.html" %}
{% load staticfiles %}
<link rel="stylesheet" href="{% static 'css/mycss.css' %}">
{# 隱藏頂部搜索框 #}
{% block search %}
{% endblock %}
{% block body %}
<div class="alert alert-success mx-auto">
    <span><h5>{{ lib_name }}-留言板管理</h5></span>
    <label><small>點(diǎn)擊留言內(nèi)容可回復(fù)留言</small></label>
</div>

<ul class="list-group">
    {% for msg in pageInfo %}
    {% if msg.parent_msgid == NULL %}
    <div class="alert alert-info">
        <lable>由 <strong>{{ msg.from_user }}</strong>&nbsp;&nbsp;<small>{{ msg.date }} </small>留言</lable>
        <li class="list-group-item" data-toggle="modal" data-target="#modal{{ forloop.counter }}">{{ msg.content }}</li>
    </div>
    <div class="modal fade" id="modal{{ forloop.counter }}">
        <div class="modal-dialog">
            <div class="modal-content">
                <!-- 模態(tài)框主體 -->
                <form  action="{% url 'lib_msgadmin' page %}" method="POST">
                    {% csrf_token %}
                    <input type="hidden" name="msgid" value="{{ msg.msgid }}">
                    <div class="form-group alert alert-info col-sm-12">
                        <label for="comment">回復(fù)用戶:<strong>{{ msg.from_user }}</strong></label>
                        <textarea class="form-control" rows="5" name="content" id="comment" placeholder="回復(fù)留言..." required></textarea>    
                        <button type="submit" class="btn btn-primary">回復(fù)</button>
                    </div>
                </form>
            </div>
        </div>
    </div>
    {% else %}
    <div class="alert alert-info">
        <lable>由 <strong>{{ msg.parent_msgid.from_user }}</strong>&nbsp;&nbsp;<small>{{ msg.parent_msgid.date }} </small>留言
        <li class="list-group-item">{{ msg.parent_msgid.content }}</li>
    </div>
    <div class="alert alert-warning">
        <div class="clearfix">
            <div class="float-right">
                <lable>由 <strong>{{ msg.from_user }}</strong>&nbsp;&nbsp;<small>{{ msg.date }} </small>回復(fù)</lable>  
            </div>
        </div>
        <li class="list-group-item">{{ msg.content }}</li>   
    </div>
    {% endif %}
    {% endfor %}
</ul>

{# 分頁 #}
<div class="center">
<ul class="pagination">
    {% if pageInfo.has_previous %}
    <li class="page-item"><a class="page-link" href="{% url 'lib_msgadmin' pageInfo.previous_page_number %}">上一頁</a></li>
    {% endif %}
    {% if pageInfo.has_next %}
    <li class="page-item"><a class="page-link" href="{% url 'lib_msgadmin' pageInfo.next_page_number %}">下一頁</a></li>
    {% endif %}
</ul>
</div>
{% endblock %}

回復(fù)留言


image.png

回復(fù)后的效果


image.png

留言板里的效果


image.png

如果需要對(duì)留言板有一個(gè)控制,比如能夠屏蔽某些非法留言,就可以用到msg_status這個(gè)字段,數(shù)據(jù)表中默認(rèn)是 1,我們把它該成非1的值就能實(shí)現(xiàn)屏蔽留言的功能。
首先到瀏覽展示的模板文件message.html中添加一個(gè)條件判斷。

 {% if msg.msg_status == 1 %}

然后在留言板管理后臺(tái)模板lib_msgadmin.html添加一個(gè)屏蔽留言的功能按鈕

        {% if msg.msg_status == 1 %}
            <div class="float-right">
                <a href="{% url 'lib_msgadmin' page %}?msgid={{ msg.msgid }}"><button type="text" class="btn btn-secondary">屏蔽該留言</button></a>
            </div>
            {% else %}
            <div class="float-right">
                <button type="text" class="btn btn-secondary">已屏蔽</button>
            </div>
            {% endif %}

模板將瀏覽的msgid通過GET參數(shù)傳遞給視圖函數(shù)處理。
視圖函數(shù)中多做一個(gè)If判斷,將GET獲取到的msgid的msg_status設(shè)置為0或任意其他值即可實(shí)現(xiàn)留言的屏蔽。

 #如果通過GET獲取到了msgid,說明是管理員用戶要屏蔽該條留言
        if request.GET.get('msgid'):
            msgid = request.GET.get('msgid')
            #將留言狀態(tài)設(shè)置為0
            Message.objects.filter(msgid=msgid).update(msg_status=0)

image.png

點(diǎn)擊屏蔽按鈕后,該條留言成為已屏蔽狀態(tài),進(jìn)入留言板模板可以發(fā)現(xiàn)被屏蔽的留言不見了。


image.png

但是,我們發(fā)現(xiàn)留言被屏蔽了2條,現(xiàn)在第一頁只有3條留言了,被屏蔽的留言雖然沒有顯示,但還是被從數(shù)據(jù)庫中讀取出來了,這種情況,我們只要在查詢數(shù)據(jù)的時(shí)候再加 msg_status=1 這個(gè)條件,這樣讀取的就全是正常狀態(tài)的留言了。

#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')

現(xiàn)在再看留言板,第一頁就是完整的5條留言了。


image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容