在写博客的过程我们可以发现,文章正文的格式十分单一,而且没有评论功能,这怎么能和别人互动呢?这一节我们要实现markdown和多说评论功能。
Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用。Markdown的语法十分简单,常用的标记符号也不超过十个,而且markdown和html语法可完美兼容。本博客到目前为止的所有文章都是有markdown语法写成。
这里推荐markdown的一些资料:markdown官网, 语法快速入门,Markdown——入门指南
Markdown的实现
首先安装markdown2,在PyCharm用Project Interpreter或者用虚拟环境下命令行安装都可以,不多说了。
接下来只要用markdown2过滤文章正文text就可以了。在views.py导入插件:
import markdown2
然后在post_list,post_detail,post_draft_list,search_tag,blog_search等逻辑中进行markdown过滤,过滤位置就在返回posts或者post_list参数前。比如post_list的过滤就是:
def post_list(request):
postsAll = Article.objects.annotate(num_comment=Count('id')).filter(
published_date__isnull=False).order_by('-published_date')
for p in postsAll:
p.click = cache_manager.get_click(p)
paginator = Paginator(postsAll, 10) # Show 10 contacts per page
page = request.GET.get('page')
posts = []
try:
posts = paginator.page(page)
except PageNotAnInteger:
# If page is not an integer, deliver first page.
posts = paginator.page(1)
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
posts = paginator.page(paginator.num_pages)
finally:
for pp in posts:
pp.text = markdown2.markdown(pp.text, extras=['fenced-code-blocks'], )
return render(request, 'blog/post_list.html', {'posts': posts, 'page': True})
extras=['fenced-code-blocks']
使用了markdown的一个重要特性fetch code。通常markdown要标记一段代码时,必须在每行代码前缩进 4 个空格,这很不方便。而 fetch code可以让我们在写文章时只按照下面的输入就可以标记一段代码,相比每行缩进四个空格要方便很多:
[```](实际中去掉中括号)
def test_function():
print('fectch code like this!')
[```]
要注意的是,三个`的位置在主键盘按键1左边,tab上面,也就是波浪线~的按键,而不是单引号,而且要在英文半角下输入才有效,另外前面要空一行。
另外,与views一一对应,在显示文章正文的模板上为正文text再增加一个safe过滤器,比如post_list.html的text就由<p>{{ post.text|linebreaks|truncatewords:5 }}</p>
变为<p>{{ post.text|safe|linebreaks|truncatewords:5 }}</p>
使用新学会的markdown语法试一下吧!
多说评论功能
在Django1.5版本前是有内置的评论系统的,不过现在已经放弃使用了。在多说网站上注册账号或者直接用社交账号进行登录,并生成一个short_name。
可以在个人界面中的工具中找到一段通用代码,这段代码非常重要,用于多说评论框的代码段:
<!-- 多说评论框 start -->
<div class="ds-thread" data-thread-key="请将此处替换成文章在你的站点中的ID" data-title="请替换成文章的标题" data-url="请替换成文章的网址"></div>
<!-- 多说评论框 end -->
<!-- 多说公共JS代码 start (一个网页只需插入一次) -->
<script type="text/javascript">
var duoshuoQuery = {short_name:"请在此处替换成自己的短名"};
(function() {
var ds = document.createElement('script');
ds.type = 'text/javascript';ds.async = true;
ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js';
ds.charset = 'UTF-8';
(document.getElementsByTagName('head')[0]
|| document.getElementsByTagName('body')[0]).appendChild(ds);
})();
</script>
<!-- 多说公共JS代码 end -->
在mysite\templates\blog中新建一个duoshuo.html并将代码放入其中,但要做一些修改,短名请替换成自己注册的:
<!-- 多说评论框 start -->
<div class="ds-thread" data-thread-key="{{ post.id }}" data-title="{{ post.title }}" data-url="{{ post.get_absolute_url }}"></div>
<!-- 多说评论框 end -->
<!-- 多说公共JS代码 start (一个网页只需插入一次) -->
<script type="text/javascript">
var duoshuoQuery = {short_name:"yuanyeqing"};
(function() {
var ds = document.createElement('script');
ds.type = 'text/javascript';ds.async = true;
ds.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') + '//static.duoshuo.com/embed.js';
ds.charset = 'UTF-8';
(document.getElementsByTagName('head')[0]
|| document.getElementsByTagName('body')[0]).appendChild(ds);
})();
</script>
<!-- 多说公共JS代码 end -->
多说网站还有很多可实现其他更多功能的代码模板,可以多看看多试试。
然后修改models.py:
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.core.urlresolvers import reverse
class Article(models.Model):
author = models.ForeignKey(User)
title = models.CharField(max_length=200)
category = models.CharField(max_length=50, blank=True)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def get_absolute_url(self):
path = reverse('post_detail', kwargs={'pk': self.id})
return "http://127.0.0.1:8000%s" % path
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return self.title
最后修改post_detail.html:
{% extends 'blog/base.html' %}
{% block content %}
<div class="date">
{% if post.published_date %}
{{ post.published_date|date:'M d, Y' }}
{% else %}
{% if user.is_authenticated %}
<a class="btn btn-default" href="{% url 'post_publish' pk=post.pk %}">Publish</a>
{% endif %}
{% endif %}
{% if user.is_authenticated %}
<a class="btn btn-default" href="{% url 'post_edit' pk=post.pk %}"><span class="glyphicon glyphicon-pencil"></span></a>
<a class="btn btn-default" href="{% url 'post_remove' pk=post.pk %}"><span class="glyphicon glyphicon-remove"></span></a>
{% endif %}
</div>
<h3>{{ post.title }}</h3>
{% if post.category %}
<a class="post-category post-category-js" href="{% url 'search_tag' tag=post.category %}">
<span class="glyphicon glyphicon-tag"></span>{{ post.category|title }}</a>
{% endif %}
<p>{{ post.text|safe|linebreaks }}</p>
{% include "blog/duoshuo.html" %}
{% endblock %}
也就是用{% include "blog/duoshuo.html" %}
把duoshuo.html加入到当前页面中。
重启就能看到多说了!
2016.10.26