提示:(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、结果展示

Django——实现评论功能(包括评论回复)的更多相关文章

  1. Django使用forms来实现评论功能

    貌似Django从版本1.6开始就放弃了对自带的comments的使用,具体原因未查,但是现在使用Django的内部的模块也可以实现评论功能,那就是借助于forms模块,下面是我的一个小例子. 环境准 ...

  2. [个人网站搭建]·Django增加评论功能(Python3)

    [个人网站搭建]·Django增加评论功能 个人主页--> https://xiaosongshine.github.io/ 个人网站搭建github地址:https://github.com/ ...

  3. Django——实现最基础的评论功能(只有一级评论)

    我对评论功能的理解: --------(1)数据库建一个评论的表 --------(2)前端建一个提交评论的form表单 --------(3)表单提交评论内容后写入到数据库评论表中 -------- ...

  4. Django自带评论功能的基本使用

    1. 模块安装 pip install django-contrib-comments 2. 注册APP INSTALLED_APP=( #..., 'django_comments', 'djang ...

  5. django表格form无法保存评论排查步骤

    初学django项目,在网上找了个blog教程,还是很不错的,这里感谢一下博主https://www.zmrenwu.com/post/2/ 这个项目适合django初学者,是一个完整的blog项目 ...

  6. 我在做评论功能时学到的js一些思路

    在提交评论的时候,如何判断是一级评论还是二级评论(因为都是通过一个文本域提交评论),思路:声明一个全局变量,如果是回复(二级评论)那么会触发点击回复事件,在这个事件的回调函数里给全局变量设置为true ...

  7. VuePress 博客优化之增加 Vssue 评论功能

    前言 在 <一篇带你用 VuePress + Github Pages 搭建博客>中,我们使用 VuePress 搭建了一个博客,最终的效果查看:TypeScript 中文文档. 本篇讲讲 ...

  8. 一步步搭建自己的博客 .NET版(2、评论功能)

    前言 这次开发的博客主要功能或特点:    第一:可以兼容各终端,特别是手机端.    第二:到时会用到大量html5,炫啊.    第三:导入博客园的精华文章,并做分类.(不要封我)    第四:做 ...

  9. vue教程2-07 微博评论功能

    vue教程2-07 微博评论功能 <!doctype html> <html> <head> <meta charset="utf-8"& ...

  10. React.js 小书 Lesson16 - 实战分析:评论功能(三)

    作者:胡子大哈 原文链接:http://huziketang.com/books/react/lesson16 转载请注明出处,保留原文链接和作者信息. 接下来的代码比较顺理成章了.修改 Commen ...

随机推荐

  1. Web实时更新客户端数据

    1        轮询方式实现客户端数据及时更新 在基于Web的即时通信.股票行情这样的系统中,需要客户端能够及时更新内容.由于B/S架构的特性(Http连接是无状态连接, 即服务器处理完客户的请求, ...

  2. java封装基础详解

    java封装基础详解 java的封装性即是信息隐藏,把对象的属性和行为结合成一个相同的独立单体,并尽可能地隐藏对象的内部细节. 封装的特性是对属性来讲的. 封装的目标就是要实现软件部件的"高 ...

  3. GitHub标星8k,字节跳动高工熬夜半月整理的“组件化实战学习手册”,全是精髓!

    前言 什么是组件化? 最初的目的是代码重用,功能相对单一或者独立.在整个系统的代码层次上位于最底层,被其他代码所依赖,所以说组件化是纵向分层. 为什么要使用组件化? 当我们的项目越做越大的时候,有时间 ...

  4. ElementUi 表单验证失败后 页面滚动到表单验证失败位置

    1.应用场景 当进行长表单验证时 用户填写到了单子的最下面 可是已经滚动过去的部分单子验证失败 为了友好的用户体验 这时候就需要滚动到验证失败位置 2.解决思路 elementUi本身并没有提供相关获 ...

  5. Linux应用程序安装方法

    一.linux应用程序基础 1.1.应用程序与系统命令的关系 1.2.典型应用程序的目录结构 1.3.常见的软件包封装类型 二.RPM包管理工具 2.1.RPM软件包管理器Red-Hat Packag ...

  6. Git-09-常用命令

    git常用命令 一般来说,日常使用只要记住下图6个命令,就可以了.但是熟练使用,恐怕要记住60-100个命令 下面是我整理的常用 Git 命令清单.几个专用名词的译名如下. Workspace:工作区 ...

  7. CVE-2020-2883漏洞复现&&流量分析

    CVE-2020-2883漏洞复现&&流量分析 写在前面 网上大佬说CVE-2020-2883是CVE-2020-2555的绕过,下面就复现了抓包看看吧. 一.准备环境 靶机:win7 ...

  8. 题解 CF613E Puzzle Lover

    解题思路 其实仔细观察我们可以发现路径一定是一个类似于下图的一个左括号之后中间随便反复曲折,然后右边在来一个右括号. 然后对于两个括号形状的东西其实是可以利用 Hash 来判等特殊处理的. 对于中间的 ...

  9. SpringBoot返回枚举对象中的指定属性

    枚举 package com.meeno.boot.oa.employee.enums; import com.alibaba.fastjson.annotation.JSONType; import ...

  10. 【springboot】validator枚举值校验

    转自: https://blog.csdn.net/aiyaya_/article/details/78588200 一.前言 在spring项目中,校验参数功能使用hibernate validat ...