Django开发个人博客项目-(10)通过markdown完成博客的展示和完成博客详情页面

0.096字数 825阅读 9

欢迎访问我的博客:小羊驼的部落阁

博客详情页面

博客的详情页同样继承自base.html模板,可以将blog-detail.html拷贝到templates目录下。与归档、标签页面类似,按照之前的方法,分别编写视图函数与url代码:

view.py
class BlogDetailView(View):
    """
    博客详情页
    """
    def get(self, request, blog_id):
        blog = Blog.objects.get(id=blog_id)
        return render(request, 'blog-detail.html', {
            'blog': blog,

        })
urls.py

我们这里采用博客的id进行url传参

url(r'^blog/(?P<blog_id>\d+)$', BlogDetailView.as_view(), name='blog_id'),

同样,要在之前的归档与分类详情页面添加上博客的url链接:

href="{% url 'blog_id' blog.id %}"

然后在模板中将博客的标题,创建时间,分类,内容,以及标签写上就行了。这里仅对标签进行说明下,标签与博客是多对多的关系,因此可以按照如下方式获得博客的所有标签:

{% for blog_tag in blog.tag.all %}
    <a href="{% url 'tag_name' blog_tag.name %}" rel="tag"># {{ blog_tag.name }}</a>
{% endfor %}

实现博客的上一篇与下一篇功能

为了实现这个功能,我们需要在视图函数中获取该篇博客的上一篇博客以及下一篇博客。为了实现这个功能,我们需要考虑到以下2种情况:

博客的id号有可能是不连续的,当我们删除一篇博客时,连带着该id号一块删除了,如果通过blog_id - 1和blog_id+1来获取博客的上一篇与下一篇,则有可能会出错。
如果是第一篇博客,它是没有上一篇的;同样,最后一篇博客也是没有下一篇的
因此,我们可以使用状态码has_prev和has_next来判断博客是否有上一篇和下一篇,并通过对id进行循环来判断id号码的连续性,实现代码如下:

view.py
#实现博客上一篇与下一篇功能

has_prev = False
has_next = False
id_prev = id_next = int(blog_id)
blog_id_max = Blog.objects.all().order_by('-id').first()
id_max = blog_id_max.id
while not has_prev and id_prev >= 1:
    blog_prev = Blog.objects.filter(id=id_prev - 1).first()
    if not blog_prev:
        id_prev -= 1
    else:
        has_prev = True
while not has_next and id_next <= id_max:
    blog_next = Blog.objects.filter(id=id_next + 1).first()
    if not blog_next:
        id_next += 1
    else:
        has_next = True

#将状态码与上下博客传递给前端页面
'blog_prev': blog_prev,
'blog_next': blog_next,
'has_prev': has_prev,
'has_next': has_next,

blog-detail.html

#判断是否有上一篇
<div class="post-nav">
        <div class="post-nav-next post-nav-item">
            {% if has_prev %}
                <a href="{% url 'blog_id' blog_prev.id %}" rel="prev"
                   title="{{ blog_prev.title }}">
                    <i class="fa fa-chevron-left"></i> {{ blog_prev.title }}
                </a>
            {% endif %}
        </div>
        <span class="post-nav-divider"></span>
        <div class="post-nav-prev post-nav-item">
            {% if has_next %}
                <a href="{% url 'blog_id' blog_next.id %}" rel="next"
                   title="{{ blog_next.title }}">
                    {{ blog_next.title }} <i class="fa fa-chevron-right"></i>
                </a>
            {% endif %}
        </div>
    </div>

如此,即可实现博客的上一篇与下一篇功能。

markdown

什么是markdown语法,我们的CSDN、简书、博客园等都是用的markdown语法。它规则很简单,可以参考如下资料:

Markdown——入门指南

安装markdown

进入虚拟环境:

pip install markdown
pip install django-mdeditor

在INSTALLED_APPS中注册

...
'mdeditor',
...

将路径添加到url中

from django.urls import include, re_path
re_path(r'mdeditor/', include('mdeditor.urls')),

在models.py中将文本区域替换:

from mdeditor.fields import MDTextField #必须导入
content = MDTextField()    #注意为MDTextField()

然后在view视图中:

import markdown
class BlogDetailView(View):
    """
    博客详情页
    """
    def get(self, request, blog_id):
        blog = Blog.objects.get(id=blog_id)

        # 将博客内容用markdown显示出来
        blog.content = markdown.markdown(blog.content, extensions=[
                                     'markdown.extensions.extra',
                                     'markdown.extensions.codehilite',
                                     'markdown.extensions.toc',
                                  ])

        return render(request, 'blog_detail.html', {
            'blog': blog,
         
        })

渲染 Markdown

将 Markdown 格式的文本渲染成 HTML 文本非常简单,只需调用这个库的 markdown 方法即可。我们书写的博客文章内容存在 Blog的 content属性里,回到我们的详情页视图函数,对Blog 的 content的值做一下渲染,把 Markdown 文本转为 HTML 文本再传递给模板:

这样我们在模板中展示 {{ blog.content }} 的时候,就不再是原始的 Markdown 文本了,而是渲染过后的 HTML 文本。

blog-detail.html
{{ blog.content|safe }}

Django 出于安全方面的考虑,任何的 HTML 代码在 Django 的模板中都会被转义(即显示原始的 HTML 代码,而不是经浏览器渲染后的格式)。为了解除转义,只需在模板标签使用 safe 过滤器即可,告诉 Django,这段文本是安全的,你什么也不用做。

这样,再次刷新页面,就可以看到带有样式的博客页面了。

推荐阅读更多精彩内容