django1.10开发博客(11)——markdown与多说评论功能

在写博客的过程我们可以发现,文章正文的格式十分单一,而且没有评论功能,这怎么能和别人互动呢?这一节我们要实现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

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 124,514评论 18 136
  • Markdown 语法 之剑 2016.5.3 23:41:46 hljs.initHighlightingOnL...
    禅与计算机程序设计艺术阅读 1,343评论 1 5
  • 她们刚走到夕卦森林,山猫大盗咯提哈跳到路中间。 咯提哈是一只很狡猾的山猫,他一直在打扰豺群,就算三只雌豺也打不过...
    九翼天龙阅读 94评论 0 1