In the daily development of content related Web systems, whether Blog or CMS, if you need to add links to interact with users, you must have the function of comment. Next, you can implement the function of comment reply in Django based on Python's MPTT framework.
Note: Because the user comment function involves some problems, many content management platforms do not open this function, mainly considering labor costs, so this method can be taken out when it is collected for use.
Automatically generated comment recovery template based on the framework. Although it is simple to realize, you should calm down and take your time, otherwise you will understand.
Installation and configuration
CMD installation using command line
pip install mptt
Create app
cd Project
python manage . py startapp Comment
Configure application module
INSTALLED_APPS = [
...
#Add article application
apps. Comment ,
.......
MPTT_COMMENTS_ALLOW_ANONYMOUS = True #True means anonymous comments are allowed, otherwise they are not allowed
COMMENTS_APP = django_mptt_comments
SITE_ID = one
MIDDLEWARE = [
......
crequest.middleware. CrequestMiddleware ,
]
X_FRAME_OPTIONS = SAMEORIGIN #Set pop-up display
The file does not need to be modified
admin.py We use xadmin instead of the original version of admin, so this file does not need to modify the configuration file of the apps.py application, and it does not need to move test.py to test and execute script , no need to move
Apply models.py
# coding:utf-8
from django.db import models
from mptt.models import MPTTModel , TreeForeignKey
from apps. User.models import *
from ckeditor.fields import RichTextField
from apps. Blog.models import *
#Replace models Model is MPTTModel
class Comment ( MPTTModel ):
article_slug = models . SlugField (
default = "" ,
verbose_name = Article slug , help_text = Fill in English, letters, underscores and numbers, which cannot be repeated, and are used for quick label search ,
)
user = models . ForeignKey (
User ,
on_delete = models . CASCADE ,
related_name = comments
)
#Mptt tree structure
parent = TreeForeignKey (
self ,
on_delete = models . CASCADE ,
null = True ,
blank = True ,
related_name = children
)
#Record who the second level comments reply to, str
reply_to = models . ForeignKey (
UserProfile ,
null = True ,
blank = True ,
on_delete = models . CASCADE ,
related_name = replyers
)
comment_message = RichTextField ()
created = models . DateTimeField ( auto_now_add = True )
class MPTTMeta :
order_insertion_by = [ created ]
def __str__ ( self ):
return self . comment_message [: twenty ]
Manage adminx.py
# coding:utf-8
import xadmin
from .models import *
#Comment management
class CommentAdmin ( object ):
list_display = [ id , article_slug , user , reply_to , comment_message ]
show_bookmarks = False
xadmin . site . register ( Comment , CommentAdmin )
Views.py
# coding:utf-8
from .models import *
from apps. Blog.models import *
from django.contrib.auth.decorators import *
from django.shortcuts import *
from .Forms import *
from django.shortcuts import render , get_object_or_404 , redirect
from django.contrib.auth.decorators import login_required
from django.http import HttpResponse , JsonResponse
from .models import Comment
from MyHome.settings import *
from notifications.signals import notify
from django.contrib.auth.models import User
#Article comments
@login_required ( login_url = /userprofile/login/ )
def post_comment ( request ):
#Process POST request
if request . method == POST :
article_slug = request . GET . get ( article_slug )
comment_message = request . POST . get ( comment_message )
parent_comment_id = request . GET . get ( parent_comment_id )
comment_form = CommentForm ( request . POST )
# print("=" * 50)
# print(article_slug)
# print("=" * 50)
if comment_form . is_valid ():
new_comment = Comment ()
new_comment . comment_message = comment_message
new_comment . user = request . user
new_comment . article_slug = article_slug
#Return to the current page of the article
redirect_url = WebBaseUrl + "MyBlogDetail?article_slug=" + article_slug
#Secondary reply
if parent_comment_id :
parent_comment = Comment . objects . get ( id = parent_comment_id )
#If the reply level exceeds two levels, it will be converted to two levels
new_comment . parent_id = parent_comment . get_root () . id
#Respondent
new_comment . reply_to = parent_comment . user
new_comment . save ()
context = {
"message" : "Reply succeeded, please close the window"
}
return render ( request , Comment/reply.html , context )
new_comment . save ()
return redirect ( redirect_url )
else :
return HttpResponse ( "The form content is incorrect, please fill in again." )
#Process GET request
elif request . method == GET :
article_slug = request . GET . get ( article_slug )
parent_comment_id = request . GET . get ( parent_comment_id )
comment_form = CommentForm ()
context = {
comment_form : comment_form ,
article_slug : article_slug ,
parent_comment_id : parent_comment_id ,
}
return render ( request , Comment/reply.html , context )
#Process other requests
else :
return HttpResponse ( "Only GET/POST requests are accepted." )
Configure url.py
from django.urls import path
from apps. Comment.views import *
app_name = Comment
urlpatterns = [
#Existing code, handle the first level reply
path ( post-comment , post_comment , name = post_comment ),
#Add a new code and process the second level reply
path ( comment_reply , post_comment , name = comment_reply )
]
Form Validation Forms.py
# coding:utf-8
from captcha.fields import CaptchaField
from django import forms
from .models import *
class CommentForm ( forms . ModelForm ):
class Meta :
model = Comment
fields = [ comment_message ]
Front end rendering template
Content reply window (pop-up window)/reply.html
<! DOCTYPE html>
< html lang = "zh-cn" >
{% load static %}
< head >
< meta charset = "utf-8" >
< link rel = "stylesheet" href = "{% static Blog/bootstrap.min.css %}" >
< link rel = "stylesheet" href = "{% static Blog/prism.css %}" >
< script src = "{% static Blog/prism_patched.min.js %}" ></ script >
< script src = "{% static ckeditor/ckeditor-init.js %}" ></ script >
< script src = "{% static ckeditor/ckeditor/ckeditor.js %}" ></ script >
< script src = "{% static Blog/js/jquery/jquery-3.3.1.js %}" ></ script >
< script src = "{% static Blog/js/popper/popper-1.14.4.js %}" ></ script >
< script src = "{% static Blog/js/bootstrap/js/bootstrap.min.js %}" ></ script >
< script src = "{% static Blog/js/csrf.js %}" ></ script >
< style >
. class_form {
width : one hundred % ;
}
</ style >
</ head >
< body >
{% if message %}
{{ message }}
Click anywhere outside the window to return.
{% else %}
< form action = "{% url comment:comment_reply %}?article_slug={{ article_slug }}&parent_comment_id={{ parent_comment_id }}"
method = "POST" class = "class_form" >
{% csrf_token %}
< div class = "col-md-12 col-sm-12" >
{{ comment_form.comment_message }}
</ div >
< button class = "btn btn-primary" > Submit comments </ button >
</ form >
{% endif %}
</ body >
</ html >
Comment section/article.html
< div class = "comments mt-30" >
{ % load mptt_tags % }
{ % if comments . count != zero % }
< h4 class = "title-t text-uppercase text-bold d-black mb-40" > {{ comments . count }}
Comments </ h4 >
{ % recursetree comments % }
{ % with comment = node % }
< div class = "comment mt-30" >
< div class = "{ % i f comment.parent %} comment mt-30 pull-in { % e lse %} comment mt-30 { % e ndif %}" >
< img class = "pull-left"
src = "{{ MEDIA_URL }}{{ comment.user_image }}"
style = "width: 63px"
alt = "" >
< div class = "comment-content bubble" >
< h5 class = "fz-13 text-bold text-uppercase d-black" > {{ comment . user }} </ h5 >
< h6 class = "orange-light text-uppercase mt-10" >
{{ comment . created | date : "Y-m-d H:i" }} </ h6 >
< p class = "fz-13 lh-28 mt-10" > {{ comment . comment_message | safe }} </ p >
< div class = "text-right mt-30" >
< ! -- load modal Button for -->
{ % if user . is_authenticated % }
< button type = "button"
class = "btn btn-trans text-uppercase ls-2"
onclick = "new_comment({{ blog_info.article_slug }}, {{ comment.id }})" >
reply
</ button >
{ % else % }
< a class = "btn btn-light btn-sm text-muted"
href = "{ % u rl User:UserLogin %}" >
Reply after login
</ a >
{ % endif % }
</ div >
< div class = "modal fade"
id = "comment_{{ comment.id }}"
tabindex = "-1"
role = "dialog"
aria - labelledby = "CommentModalCenter"
aria - hidden = "true" >
< div class = "modal-dialog modal-dialog-centered modal-lg"
role = "document" >
< div class = "modal-content" style = "height: 400px" >
< div class = "modal-header" >
< h5 class = "modal-title" id = "exampleModalCenterTitle" >
reply {{ comment . user }} : </ h5 >
</ div >
< div class = "modal-body"
id = "modal_body_{{ comment.id }}" ></ div >
</ div >
</ div >
</ div >
{ % if not comment . is_leaf_node % }
< div class = "children" >
{{ children }}
</ div >
{ % endif % }
</ div >
</ div >
</ div >
< div class = "clearfix" ></ div >
{ % endwith % }
{ % endrecursetree % }
{ % else % }
< h3 > No comment at the moment. Come and express your opinion </ h3 >
{ % endif % }
</ div >
Display comment section/article.html
< div class = "leave-comment mt-50" >
< h4 class = "title-t text-bold text-uppercase d-black" > Leaving a message. </ h4 >
< div class = "clearfix" ></ div >
< hr >
{ % if user . is_authenticated % }
< form action = "{ % u rl comment:post_comment %}? article_slug={{ blog_info.article_slug }}"
method = "POST" >
{ % csrf_token % }
{{ comment_form . comment_message }}
< div class = "mt-30" >
< input name = "submit" type = "submit" class = "btn btn-orange-light text-uppercase"
id = "submit" value = "Submit comments" >
</ div >
</ form >
{ % else % }
< br >< h5 class = "row justify-content-center" >
please < a href = "{ % u rl User:UserLogin %}" > Sign in </ a > Reply later
</ h5 >< br >
{ % endif % }
</ div >
</ div >
The call part of ckeditor and js
< script src = "{ % s tatic ckeditor/ckeditor-init.js %}" ></ script >
< script src = "{ % s tatic ckeditor/ckeditor/ckeditor.js %}" ></ script >
< script >
// load modal
function new_comment ( article_slug , comment_id ) {
let modal_body = #modal_body_ + comment_id ;
let modal_id = #comment_ + comment_id ;
// Load Editor
if ( $ ( modal_body ) . children () . length === zero ) {
let content = <iframe src="{ % u rl comment : post_comment %}? article_slug= +
article_slug +
&parent_comment_id= +
comment_id +
" frameborder="0" style="width: 100%; height: 100%; "></iframe> ;
$ ( modal_body ) . append ( content );
}
;
$ ( modal_id ) . modal ( show );
}
</ script >