Django——實現評論功能(包括評論回復)


提示:(1)功能不全面,僅僅實現評論(2)樣式簡單

 

1、項目目錄結構

 

 

2、模型

 

from django.db import models
from django.contrib.auth.models import User


class Article(models.Model):    #定義文章模型類
    title = models.CharField(max_length=100,verbose_name='文章標題')   #verbose_name是
    content = models.TextField(verbose_name='文章內容')
    publish_time = models.DateTimeField(auto_now_add=True,verbose_name='發布時間')
    author = models.ForeignKey(User,on_delete=models.DO_NOTHING,verbose_name='作者')

    class Meta:
        db_table = 'article_tb'     #定義表名
        verbose_name = '文章'       #后台顯示
        verbose_name_plural = verbose_name    #后台顯示的復數




class Comment(models.Model):    #定義評論模型
    article = models.ForeignKey(to=Article,on_delete=models.DO_NOTHING,verbose_name='評論文章')
    comment_content = models.TextField(verbose_name='評論內容')
    comment_author = models.ForeignKey(to=User,on_delete=models.DO_NOTHING,verbose_name='評論者')
    comment_time = models.DateTimeField(auto_now_add=True,verbose_name='評論時間')
    pre_comment = models.ForeignKey('self',on_delete=models.DO_NOTHING,null=True,verbose_name='父評論id')  #父級評論,如果沒有父級則為空NULL, "self"表示外鍵關聯自己

    class Meta:
        db_table = 'comment_tb'
        verbose_name = '評論'
        verbose_name_plural = verbose_name

  

 

3、路由:

from django.contrib import admin
from django.urls import path,re_path
from myapp import views       #導入myapp中的視圖函數

urlpatterns = [
    path('admin/', admin.site.urls),
    path('register/',views.register),            #用戶注冊路由
    path('user_login/',views.user_login),        #用戶登錄路由
    path('index/',views.index),                  #首頁路由
    re_path('article_detail/(\d)/',views.article_detail),  #文章詳情頁路由,並傳入文章的id
    path('comment_control/',views.comment_control)   #提交評論處理的路由
]

  

4、視圖函數

from django.http import JsonResponse
from django.shortcuts import render,HttpResponse,redirect
from django.contrib import auth                #使用Django的auth認證組件
from django.contrib.auth.models import User    #使用Django的認證組件需要使用User用戶表
from myapp.models import Article               #導入Article模型
from myapp.models import Comment               #導入Comment模型



def register(request):  #用戶注冊函數
    if request.method == 'GET':
        return render(request,'register.html')   #返回一個注冊的頁面
    else:
        username = request.POST.get('username')  #獲取注冊輸入的信息
        password = request.POST.get('password')
        User.objects.create_user(username=username,password=password)  #在User表創建用戶記錄
        return HttpResponse('注冊成功')





def user_login(request):   #用戶登錄函數
    if request.method == 'GET':
        return render(request,'user_login.html')
    else:
        username = request.POST.get('username')     #獲取登錄輸入的信息
        password = request.POST.get('password')
        user = auth.authenticate(username=username,password=password)  #用戶驗證
        if user:
            auth.login(request,user)         #認證成功則保持登錄狀態
            return HttpResponse('登陸成功')
        else:
            return redirect('/user_login/')  #認證失敗則跳轉到登錄頁面進行重新登錄






def index(request):    #首頁函數
    if request.user.username:      #判斷用戶是否已登錄(用戶名是否存在)
        all_article_list = Article.objects.all()    #取出所有的文章對象,結果返回一個QuerySet[]對象
        context = {
            'all_article_list': all_article_list
        }
        return render(request,'index.html',context=context)         #返回首頁的頁面,並將文章對象傳到模板進行渲染
    else:
        return redirect('/user_login/')   #如果用戶沒有登錄,則跳轉至登錄頁面






def article_detail(request,article_id):
    if request.user.username:
        article = Article.objects.get(id=article_id)    #從數據庫找出id=article_id的文章對象
        comment_list = Comment.objects.filter(article_id=article_id)  #從數據庫找出該文章的評論數據對象
        context = {
               'article': article,
               'comment_list': comment_list
        }
        return render(request,'article_detail.html',context=context)  #返回對應文章的詳情頁面
    else:
        return redirect('/user_login/')





def comment_control(request):    #提交評論的處理函數

    if request.user.username:
        comment_content = request.POST.get('comment_content')
        article_id = request.POST.get('article_id')
        pid = request.POST.get('pid')
        author_id = request.user.id     #獲取當前用戶的ID

        Comment.objects.create(comment_content=comment_content,pre_comment_id=pid,article_id=article_id,comment_author_id=author_id)  #將提交的數據保存到數據庫中

        article = list(Comment.objects.values('id','comment_content','pre_comment_id','article_id','comment_author_id','comment_time'))  #以鍵值對的形式取出評論對象,並且轉化為列表list類型

        return JsonResponse(article,safe=False)   #JsonResponse返回JSON字符串,自動序列化,如果不是字典類型,則需要添加safe參數為False
    else:
        return redirect('/user_login/')

  

5、模板templates

(1)注冊頁面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>注冊頁面</title>
</head>
<body>
    <h6>注冊</h6>
    <form action="" method="post">    {# 注冊提交信息的表單,POST方式提交注冊信息 #}
        <input type="text" placeholder="用戶名" name="username">
        <input type="password" placeholder="密碼" name="password">
        <input type="submit" value="注冊">
    </form>

</body>
</html>

  

(2)登錄頁面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>登錄頁面</title>
</head>
<body>
    <h6>登錄</h6>
    <form action="" method="post">    {# 登錄時提交信息的表單,POST方式 #}
        <input type="text" placeholder="用戶名" name="username">
        <input type="password" placeholder="密碼" name="password">
        <input type="submit" value="登錄">
    </form>

</body>
</html>

  

(3)首頁

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首頁</title>
    <style>
        .article{
            width: 80%;
        }
        .article_list{
            width: 100%;
            border: red 1px dashed;
        }
        .article .article_list th{
            text-align: center;
            border: 1px skyblue dashed;
        }
        .article .article_list td{
            text-align: center;
            border: 1px green dashed;
        }
    </style>
</head>
<body>
    <div class="article">
        <table class="article_list">
            <tr>
                <th>文章ID</th>
                <th>文章標題</th>
                <th>文章內容</th>
                <th>發布時間</th>
                <th>作者</th>
            </tr>
            {% for article in all_article_list %}
            <tr>
                <td>{{ article.id }}</td>
                <td><a href="/article_detail/{{ article.id }}/">{{ article.title }}</a>   {# 點擊鏈接打開文章詳情頁,並傳入文章的ID #}
                <td>{{ article.content }}</td>
                <td>{{ article.publish_time | date:"Y-m-d H:i:s"}}</td>
                <td>{{ article.author }}</td>
            </tr>
            {% endfor %}

        </table>
    </div>
</body>
</html>

  

(4)文章詳情頁

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>文章詳情</title>
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js"></script>
    <style>
        .article_detail{
            width: 80%;
            margin-left: 100px;
        }
        .comment_post{
            width: 80%;
            margin-left: 100px;
        }
        .comment_show{
            width: 80%;
            margin-left: 100px;
        }
        #commentform_title {
            background-image: url(//static.cnblogs.com/images/icon_addcomment.gif);
            background-repeat: no-repeat;
            padding: 0 0 0 25px;
            margin-bottom: 10px;
        }
        .feedback_area_title {
            border-bottom: 1px solid #ddd;
            font-size: 14px;
            font-weight: bold;
            margin: 20px 0 10px;
        }
        #p{
            border: deepskyblue 1px dashed;
            background-color: antiquewhite;
        }
    </style>
</head>
<body>
    <div class="article_detail">    {# 文章詳情區域的div #}
        <h4>{{ article.title }}</h4>
        <p>{{ article.content }}</p>
        <p>發布時間:{{ article.publish_time | date:"Y-m-d H:i:s"}}    作者:{{ article.author }}</p>
    </div>


    <div class="comment_post">      {# 提交評論區域的div #}
        <div id="commentform_title">發表評論</div>
        <textarea rows="10" cols="60" id="comment_content"></textarea>
        <p><button>提交評論</button></p>
    </div>


    <div class="comment_show">      {# 評論展示區域的div #}
        <div class="feedback_area_title">評論列表</div>
        <div class="comment_list">
            {% for comment in comment_list %}    {# 循環展示評論的數據 #}
                <div>
                    <p>第{{ forloop.counter}}樓 -> By:{{ comment.comment_author.username }} -> {{ comment.comment_time }} -> <button class="reply" username={{ comment.comment_author.username }} pk={{ comment.pk }}>回復</button></p>  {# 在此處定義一個回復按鈕,用戶實現子評論,並且自定義屬性username和pk,用於下面回復功能的實現 #}
                    {% if comment.pre_comment_id %}   {# 判斷評論是否有父級評論 #}
                        <p id="p">原評論內容:{{ comment.pre_comment.comment_content }}</p>  {# 如果有父級評論,則在中間顯示父級評論的評論內容 #}
                    {% endif %}
                    <p>評論內容:{{ comment.comment_content }}</p>
                    <hr>
                </div>
            {% endfor %}
        </div>
    </div>


    {# 提交評論的JS,發送Ajax請求 #}
    <script>
        var pid = ""        {# 設置一個變量pid默認為空,用於后面作為數據庫存儲的父級評論的ID,如果沒有父級評論則為空,子評論有父級評論 #}
        {# 提交評論按鈕的點擊事件 #}
        $(".comment_post p button").click(function (){
            $.ajax({
                url: '/comment_control/',
                type: 'post',
                data: {
                    comment_content: $("#comment_content").val(),  {# 提交的數據內容data #}
                    article_id: {{ article.id }},
                    pid: pid
                },
                success: function (res){            {# 本例中返回的數據僅僅用於在控制台打印而已 #}
                    console.log(res)                {# 控制台打印返回的數據 #}
                    $("#comment_content").val("")   {# 提交完成后,清空評論輸入框的內容 #}
                    pid = ""                        {# 子評論提交完成后,將pid默認設置為空,恢復為默認的父評論 #}

                }
            })
        })


        {# 回復按鈕的點擊事件 #}
        $(".reply").click(function (){
            $("#comment_content").focus()       {# 回復按鈕的事件,點擊時,將光標聚集到評論輸入框中 #}
            var val = "@" + $(this).attr("username") + "\n"    {# $(this)指代".reply"標簽本身,獲取這個標簽的username值 #}
            $("#comment_content").val(val)      {# 回復時,自動在輸入框加入:@要回復的人 #}
            pid = $(this).attr("pk")            {# 當點擊回復時,父評論ID不再為空,此時修改為:對應評論的主鍵值ID #}
        })

    </script>

</body>
</html>

  

 

6、數據庫表

 

 

 

 

7、結果展示

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM