6.1.comments plug-in unit

(1) install

pip install django-contrib-comments

(02)settings

INSTALLED_APPS = [
'django.contrib.sites',
'django_comments',
]
SITE_ID =1

(3)website/url

 url(r'^comments/', include('django_comments.urls')),

(4) Modify source code

django_comments/abstracts.py The first 36 That's ok

Source code

 site = models.ForeignKey(Site, on_delete=models.CASCADE)

After modification

 site = models.ForeignKey(Site,default=None,blank=True,null=True,on_delete=models.CASCADE)

(5) Modify source code

django_comments/abstracts.py The first 52 That's ok

Several fields have been modified and added

class CommentAbstractModel(BaseCommentAbstractModel):
"""
A user comment about some object.
""" # Who posted this comment? If ``user`` is set then it was an authenticated
# user; otherwise at least user_name should have been set and the comment
# was posted by a non-authenticated user.
user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=_('user'),
blank=True, null=True, related_name="%(class)s_comments",
on_delete=models.SET_NULL) # Explicit `max_length` to apply both to Django 1.7 and 1.8+.
user_email = models.EmailField(_("user's email address"), max_length=254,
blank=True,null=True,default='xxx@xxx.com')
user_url = models.URLField(_("user's URL"), blank=True,null=True,default='https://xxx.xxx.xxx.xxx') user_name = models.CharField(_("user's name"), max_length=50, blank=True)
user_img = models.ImageField(upload_to="user_images", blank=True,null=True,verbose_name=" User image ")
comment_title = models.CharField(max_length=256,default=" No title ", blank=True,null=True,verbose_name=" Comment title ")
parent_comment = models.ForeignKey('self',default=None, blank=True,null=True,related_name="child_comment",on_delete=models.CASCADE)
level = models.PositiveIntegerField(default=0, blank=True,null=True,verbose_name=' Comment hierarchy ') comment = models.TextField(_('comment'), max_length=COMMENT_MAX_LENGTH)
.
.
.
.

(6) Modify source code

django_comments/admin.py The first 29 and 37 That's ok

_('Content'),
{'fields': ('user', 'user_name', 'user_email', 'user_url', 'comment','comment_title','parent_comment')}
list_display = ('comment_title','name', 'content_type', 'object_pk', 'ip_address', 'submit_date', 'is_public', 'is_removed')

(7) Modify source code

django_comments/forms.py The first 97 Line form

 class CommentDetailsForm(CommentSecurityForm):   
 """

Handles the specific details of the comment (name, comment, etc.).
"""
# name = forms.CharField(label=pgettext_lazy("Person name", "Name"), max_length=50)
# email = forms.EmailField(label=_("Email address"))
# url = forms.URLField(label=_("URL"), required=False)
# Translators: 'Comment' is a noun here.
comment = forms.CharField(label=_('Comment'), widget=forms.Textarea,
max_length=COMMENT_MAX_LENGTH)
comment_title = forms.CharField(max_length=256,label=_(' title '))
parent_id = forms.IntegerField(min_value=-1,label=_(' The father commented on id'))
level = forms.IntegerField(min_value=0,label=_(' Hierarchy '),)
.
.
.

def get_comment_create_data(self, site_id=None):
"""
Returns the dict of data to be used to create a comment. Subclasses in
custom comment apps that override get_comment_model can override this
method to add extra fields onto a custom comment model.
"""
parent_id = self.cleaned_data['parent_id']
if parent_id <= 0:
parent = None
_level = self.cleaned_data['level']
else:
parent = get_model().objects.get(id=parent_id)
_level = self.cleaned_data['level'] + 4 # 4 It's indentation return dict(
content_type=ContentType.objects.get_for_model(self.target_object),
object_pk=force_text(self.target_object._get_pk_val()),
# user_name=self.cleaned_data["name"],
# user_email=self.cleaned_data["email"],
# user_url=self.cleaned_data["url"],
comment_title = self.cleaned_data['comment_title'],
parent_comment = parent,
level = _level,
comment=self.cleaned_data["comment"],
submit_date=timezone.now(),
site_id=site_id or getattr(settings, "SITE_ID", None),
is_public=True,
is_removed=False,
)

(8) Modify source code

django_comments/views/comments.py The first 97 Line form

52 That's ok

 # add to 
if not request.session.get('login', None) and not user_is_authenticated:
return redirect("/")

116 That's ok

 # if user_is_authenticated:
# comment.user = request.user
# add to
if request.session.get('login',None):
comment.user_name = request.session['screen_name']
comment.user_img = request.session['profile_image_url']

After all the above changes

python manage.py makemigtations
python manage.py migrate

6.2. review form

detail.html

 <div class="row">
<hr />
{% get_comment_form for entry as form %}
{% get_comment_count for entry as comment_count %}
<h3 > The total number of comments : {{ comment_count }}</h3>
<hr />
</div> <div class="row">
<form class="form-horizontal" action="{% comment_form_target %}" method="post">
{% csrf_token %}
<div class="form-group">
<label for="input_title" class="pull-left control-label"> Comment title :</label>
<div class="col-sm-6">
<input class="form-control" name="comment_title" id="input_title" placeholder=" Please enter a title " required />
</div>
</div>
<div class="form-group">
<label for="input_comment" class="pull-left control-label"> Comment content :</label>
<div class="col-sm-6">
<textarea style="resize:none;" class="form-control" rows=6 name="comment" id="input_comment" placeholder=" Enter comments here " required></textarea>
</div>
</div>
<span style="display: none;">{{ form.honeypot }}</span>
{{ form.content_type }}
{{ form.object_pk }}
{{ form.timestamp }}
{{ form.security_hash }}
<input type="hidden" name="next" value="{% url 'blog:blog_detail' entry.id %}" />
<input name="parent_id" type="hidden" value="-1" />
<input name="level" type="hidden" value="" /> <div class="form-group col-sm-7">
<div class="pull-left" style="margin-left: 68px;">
<button type="reset" class="btn btn-default"><span class="glyphicon glyphicon-repeat"></span>&nbsp;&nbsp; Reset </button>
</div>
<div class="pull-right" style="margin-right: 12px;">
<button type="submit" class="btn btn-success" id="id_submit"><span class="glyphicon glyphicon-send"></span>&nbsp;&nbsp; Comment on </button>
</div>
</div>
</form>
</div>

effect :

Now test the comments , I can add success , But not yet

6.3. Show comments

(1)views.py

from django_comments.models import Comment
def detail(request,blog_id):
# entry = models.Entry.objects.get(id=blog_id)
entry = get_object_or_404(models.Entry,id=blog_id) md = markdown.Markdown(extensions=[
'markdown.extensions.extra',
'markdown.extensions.codehilite',
'markdown.extensions.toc',
])
entry.body = md.convert(entry.body)
entry.toc = md.toc
entry.increase_visiting() comment_list = list() def get_comment_list(comments):
for comment in comments:
comment_list.append(comment)
children = comment.child_comment.all()
if len(children) > 0:
get_comment_list(children) top_comments = Comment.objects.filter(object_pk=blog_id, parent_comment=None,
content_type__app_label='blog').order_by('-submit_date') get_comment_list(top_comments)
return render(request, 'blog/detail.html', locals())

(2)detail.html

<div class="row">
<hr />
{% get_comment_form for entry as form %}
{% get_comment_count for entry as comment_count %}
<h3 > The total number of comments : {{ comment_count }}</h3>
<hr />
</div> {# review form #}
{% if request.session.login or request.user.is_authenticated %}
<div class="row">
<form class="form-horizontal" action="{% comment_form_target %}" method="post">
{% csrf_token %}
<div class="form-group">
<label for="input_title" class="pull-left control-label"> Comment title :</label>
<div class="col-sm-6">
<input class="form-control" name="comment_title" id="input_title" placeholder=" Please enter a title " required />
</div>
</div>
<div class="form-group">
<label for="input_comment" class="pull-left control-label"> Comment content :</label>
<div class="col-sm-6">
<textarea style="resize:none;" class="form-control" rows=6 name="comment" id="input_comment" placeholder=" Enter comments here " required></textarea>
</div>
</div>
<span style="display: none;">{{ form.honeypot }}</span>
{{ form.content_type }}
{{ form.object_pk }}
{{ form.timestamp }}
{{ form.security_hash }}
<input type="hidden" name="next" value="{% url 'blog:blog_detail' entry.id %}" />
<input name="parent_id" type="hidden" value="-1" />
<input name="level" type="hidden" value="0" /> <div class="form-group col-sm-7">
<div class="pull-left" style="margin-left: 68px;">
<button type="reset" class="btn btn-default"><span class="glyphicon glyphicon-repeat"></span>&nbsp;&nbsp; Reset </button>
</div>
<div class="pull-right" style="margin-right: 12px;">
<button type="submit" class="btn btn-success" id="id_submit"><span class="glyphicon glyphicon-send"></span>&nbsp;&nbsp; Comment on </button>
</div>
</div> </form>
</div>
{% else %}
<h3> You can only comment after logging in </h3>
{% endif %}
<hr /> {# Comment display area #}
<div class="row">
{% for comment in comment_list %}
<div class="single_comment" style="margin-left: {{ comment.level }}em">
<div>
{% if comment.user_img %}
<img src="{{ comment.user_img }}" alt="user_image" />
{% else %}
<img src="{% static 'blog/images/cl.jpg' %}" />
{% endif %}
</div>
<div class="col-md-11 comment-content" style="margin-bottom: 10px;">
<strong>{{ comment.comment_title }}</strong>
<div>
{% if comment.parent_comment %}
{{ comment.user_name }}{{ request.user }}
<i class="glyphicon glyphicon-share-alt"></i>
{{ comment.parent_comment.user_name }}{{ request.user }}
{% else %}
By&nbsp;&nbsp;
{{ comment.user_name }}{{ request.user }}
&nbsp;&nbsp;&nbsp;On&nbsp;&nbsp;
{% endif %}
<em>{{ comment.submit_date }}</em>
{% if request.session.login or request.user.is_authenticated %}
&nbsp;&nbsp;&nbsp;<a href="#"> reply </a>
{% endif %}
</div>
<br />
<p>{{ comment.comment }}</p>
</div>
</div>
{% endfor %}
</div>
</div>

(3)static/blog/images/cl.jpg

Set the default picture ( If you are not logged in, the default image will be displayed , To test the comments )

(4)blog/blog_comment.css

hr {
border-top: 1px solid lightgrey;
border-bottom: 1px solid #fff;
} .single_comment {
margin-bottom: 20px;
font-family: "Microsoft Yahei"," Microsoft YaHei ",Arial,Helvetica,STHeiti,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";
} .single_comment img {
width:50px;
height:50px;
border-radius:50%;
overflow:hidden;
float: left;
margin-left: 10px;
margin-top: 5px;
} .single_comment p {
margin-bottom:;
} .comment-content {
border-bottom: 1px dashed lightgrey;
border-left: 1px dashed #2d7da4;
padding-bottom: 5px;
}

detail.html quote

{% block css %}
<link rel="stylesheet" href="{% static 'blog/css/github.css' %}">
<link rel="stylesheet" href="{% static 'blog/css/blog_comment.css' %}">
{% endblock %}

effect :

6.4. Comment reply

(1)blog/urls.py

 url(r'^reply/(?P<comment_id>\d+)/$', views.reply, name='comment_reply'),

(2)views.py

from django_comments import models as comment_models
def reply(request, comment_id):
if not request.session.get('login', None) and not request.user.is_authenticated():
return redirect('/')
parent_comment = get_object_or_404(comment_models.Comment, id=comment_id)
return render(request, 'blog/reply.html', locals())

(3)blog/reply.html

{% extends 'blog/base.html' %}
{% load comments %}
{% load static %}
{% block title %} Reply to comments {% endblock %}
{% block css %} <link rel="stylesheet" href="{% static 'blog/css/blog_comment.css' %}">
{% endblock %} {% block content %}
<div class="container-fluid" style="margin: 30px 50px 0 50px;min-height: 450px;">
<div class="row">
<div class="single_comment">
<div>
{% if request.session.login %}
<img src="{{ parent_comment.user_img }}" alt="user_img" />
{% else %}
<img src="{% static 'blog/images/cl.jpg' %}" alt="admin_img" />
{% endif %}
</div>
<div class="col-md-11">
<strong>{{ parent_comment.comment_title }}</strong>
<div class="small">
<strong>{{ parent_comment.username }} {{ request.user }}</strong>
<em>{{ parent_comment.submit_date }}</em>
</div>
<br />
<p>{{ parent_comment.comment }}</p>
</div> </div>
</div>
<br />
{% if request.session.login or request.user.is_authenticated %}
<div class="row" style="margin-left: 30px;">
<h3> reply &nbsp;&nbsp;&nbsp;{{ parent_comment.username }}{{ request.user }}&nbsp;&nbsp;&nbsp; The comments :</h3>
{% get_comment_form for parent_comment.content_object as form %}
<form class="form-horizontal" action="{% comment_form_target %}" method="post">
{% csrf_token %}
<div class="form-group">
<label for="input_title" class="pull-left control-label"> Comment title :</label>
<div class="col-sm-6">
<input class="form-control" name="comment_title" id="input_title" placeholder=" Please enter a title " required />
</div>
</div>
<div class="form-group">
<label for="input_comment" class="pull-left control-label"> Comment content :</label>
<div class="col-sm-6">
<textarea style="resize:none;" class="form-control" rows=6 name="comment" id="input_comment" placeholder=" Enter comments here " required></textarea>
</div>
</div>
<span style="display: none;">{{ form.honeypot }}</span>
{{ form.content_type }}
{{ form.object_pk }}
{{ form.timestamp }}
{{ form.security_hash }} <input type="hidden" name="next" value="{% url 'blog:blog_detail' parent_comment.content_object.id %}" />
<input name="parent_id" type="hidden" value="{{ parent_comment.id }}" />
<input name="level" type="hidden" value="{{ parent_comment.level }}" /> <div class="form-group col-sm-7">
<div class="pull-left" style="margin-left: 68px;">
<button type="reset" class="btn btn-default"><span class="glyphicon glyphicon-repeat"></span>&nbsp;&nbsp; Reset </button>
</div>
<div class="pull-right" style="margin-right: 12px;">
<button type="submit" class="btn btn-success" id="id_submit"><span class="glyphicon glyphicon-send"></span>&nbsp;&nbsp; Comment on </button>
</div>
</div> </form>
</div>
{% else %}
<h3> You can only comment after logging in </h3>
{% endif %}
<br /> <div>
<a href="{% url 'blog:blog_detail' parent_comment.content_object.id %}"> No comment for the moment , Go back to the previous page !</a>
</div> </div>
{% endblock %}

(4)detail.html

<a href="{% url 'blog:comment_reply' comment.id %}"> reply </a>

The test reply function is as follows :

6.5. Sina Weibo login

(1)settings

CLIENT_ID = 224188xxx
APP_SECRET = '76daf2e9e424xxxx71144154f5xx32xx'

(2)website/urls.py

url(r'^login/$', blog_views.login),
url(r'^logout/$', blog_views.logout),

(3)views.py

def login(request):
import requests
import json
from django.conf import settings
code = request.GET.get('code', None)
if code is None:
return redirect('/') access_token_url = 'https://api.weibo.com/oauth2/access_token?client_id=%s&client_secret=%s&grant_type=authorization_code&redirect_uri=http://127.0.0.1:8000/login&code=%s'\
%(settings.CLIENT_ID, settings.APP_SECRET, code) ret = requests.post(access_token_url) data = ret.text # The data returned by Weibo is json Format data_dict = json.loads(data) # convert to python Dictionary format token = data_dict['access_token']
uid = data_dict['uid'] request.session['token'] = token
request.session['uid'] = uid
request.session['login'] = True user_info_url = 'https://api.weibo.com/2/users/show.json?access_token=%s&uid=%s' % (token, uid)
user_info = requests.get(user_info_url) user_info_dict = json.loads(user_info.text) # Get the information of microblog users request.session['screen_name'] = user_info_dict['screen_name']
request.session['profile_image_url'] = user_info_dict['profile_image_url'] return redirect(request.GET.get('next', '/')) def logout(request):
if request.session['login']:
del request.session['login']
del request.session['uid']
del request.session['token']
del request.session['screen_name']
del request.session['profile_image_url']
return redirect(request.Get.get('next', '/'))
else:
return redirect('/')

(4)base.html

 <ul class="nav navbar-nav navbar-right">
{% if request.session.login %}
<li>{{ request.session.screen_name }}<a href="/logout/?next={{ request.path }}">
<i class="glyphicon glyphicon-log-out"></i> Cancellation </a></li>
{% else %}
<li>
<a href="https://api.weibo.com/oauth2/authorize?client_id=2241881638&response_type=code&redirect_uri=http://127.0.0.1:8000/login/?next={{ request.path }}">
<i class="glyphicon glyphicon-log-in"></i>&nbsp;&nbsp; Sign in </a></li>
{% endif %}
</ul>

6.6. Deploy

(1)settings

STATIC_ROOT = os.path.join(BASE_DIR,'all_static_files')

(2)uwsgi.ini

[uwsgi]
socket =127.0.0.1 :8000
chdir = /home/github_project/Myblog
module = Myblog.wsgi
master = true
processes = 4
vacuum = true
virtualenv = /root/.virtualenvs/myblog
logto = /tmp/mylog.log

(3)Myblog.conf

# the upstream component nginx needs to connect to
upstream django {
# server unix:///path/to/your/mysite/mysite.sock; # for a file socket
server 127.0.0.1:8000; # for a web port socket (we'll use this first)
}
# configuration of the server server {
# the port your site will be served on
listen 80;
# the domain name it will serve for
server_name 116.85.52.205; # substitute your machine's IP address or FQDN
charset utf-8; # max upload size
client_max_body_size 75M; # adjust to taste # Django media
location /media {
alias /home/github_project/Myblog/media; # Point to django Of media Catalog
} location /static {
alias /home/github_project/Myblog/all_static_files; # Point to django Of static Catalog
} # Finally, send all non-media requests to the Django server.
location / {
uwsgi_pass django;
include uwsgi_params; # the uwsgi_params file you installed
}
}

Django+Bootstrap+Mysql Build a personal blog ( 6、 ... and ) More articles about

  1. Django+Bootstrap+Mysql Build a personal blog ( One )

    1.1. Environment building (1) A virtual environment mkvirtualenv website pip install django==1.11.7 (2) Create projects and app:website and blog (3) Set up Chinese set ...

  2. Django+Bootstrap+Mysql Build a personal blog ( 5、 ... and )

    5.1. Customize 403,404 and 500 page (1)website/urls.py from blog import views as blog_views handler403 = blog_views ...

  3. Django+Bootstrap+Mysql Build a personal blog ( Four )

    4.1. Blog classification (1)blog_tags.py @register.simple_tag def get_categories(): return Category.objects.all() @r ...

  4. Django+Bootstrap+Mysql Build a personal blog ( 3、 ... and )

    3.1. Paging function (1)views.py from django.core.paginator import Paginator,EmptyPage,PageNotAnInteger def make ...

  5. Django+Bootstrap+Mysql Build a personal blog ( Two )

    2.1. Blog homepage design (1)settings.py MEDIA_ROOT = os.path.join(BASE_DIR,'media').replace("//","/ ...

  6. Django+Bootstrap+Mysql Build a personal blog ( 6、 ... and )

    6.1.comments plug-in unit (1) install pip install django-contrib-comments (02)settings INSTALLED_APPS = [ 'django.con ...

  7. Python Web Development :Django+BootStrap Implement a simple blog project

    establish blog Project structure About how to create one Django project , Please check out [Python Web Development : Use Django Framework creation HolleWorld project ] establish blog Data model of Create an article class All development is data ...

  8. django introduction --django-blog-zinnia Build a personal blog

    1. install python Choose the right python2.7 And above https://www.python.org/downloads/ 2. Build a virtual environment It's not necessary , But it is recommended to use , Introduce dependencies separately for each project , ...

  9. Django Two days to build a personal blog

    Portal :https://github.com/1417766861/django-blog( Direct operation , There are steps ) effect : home page : Sidebar : Details page : Modify the head image , Information , Article release : Support tag drag and drop ...

Random recommendation

  1. css common Universal

    /*common*/ body{ color:#666666; font-size:12px; margin:; padding:; font-family:"Arial",&qu ...

  2. Microsoft YaHei stay css How to write in

    1. First of all, understand css How to control fonts in . font: Set all font properties in one declaration : font There are several properties : font-style: Font style font-variant: The font is different font-weight ...

  3. AES encryption 16 Conversion between decimal and binary

    import java.security.Key; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax ...

  4. selenuim ide Problems with playback

    [error] Unexpected Exception: fileName -> chrome://selenium-ide/content/selenium-core/scripts/htm ...

  5. Python The eleventh day of the road , senior (3)- Thread pool

    Thread pool Simple thread pool implementation : import queue import threading import time class ThreadPool(object): def __init__(self ...

  6. MAC COCOA call command Call the terminal console program

    MAC COCOA call command Call the terminal console program STEP 1 Write a first C++ DOS Program STEP2 Use NSTask To run the , And then use NSPipe and NSData To accept the result string of the run ...

  7. There are three ways to realize waterfall flow ( Native js+jquery+css3)

    Preface The project needs a waterfall page , It's using waterfall This plugin , It feels OK , I don't have my own handwriting when I catch up with the project . I have nothing to do recently , Just write your own . The general idea is clear , It's still very good to achieve ... Native javascript edition ...

  8. X64 Under the system IIS function ASP Website HTTP500 error 【 install FoxMail Server When 】

    The error is as above terms of settlement Run in administrator mode CMD Input cscript C:\inetpub\adminscripts\adsutil.vbs SET W3SVC/AppPools/Enable32bitA ...

  9. be based on ARM_contexA9 led Drive programming

    About the friendly arm contexA9 Development board , At present, there are few resources on the network , Especially in the kernel , Very little , In view of this situation , I'm going to write a series of drivers to do about tiny4412 Summary of this board development . A brief introduction : Tiny4 ...

  10. 【XSY2519】 Neuron prufer Sequence DP

    Title Description Yes \(n\) spot , Each point has a degree limit ,\(\forall i(1\leq i\leq n)\), Let you choose \(i\) A little bit , Build another spanning tree , It is required that the degree of each point does not exceed the degree limit . How many options do you have . \( ...