欢迎访问我的博客:小羊驼的部落阁
博客详情页面
博客的详情页同样继承自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
进入虚拟环境:
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,这段文本是安全的,你什么也不用做。
这样,再次刷新页面,就可以看到带有样式的博客页面了。