本渣渣不专注技术,只专注使用技术,不是一个资深的coder,是一个不折不扣的copier |
1、博客详情页面
博客的详情页同样继承自 base.html 模板,侧边栏就不需要了,这里老规矩,不一块一块的讲解,这个自己要
blog -> storm -> view.py
class DetailView(generic.DetailView):
"""
Django有基于类的视图DetailView,用于显示一个对象的详情页,我们继承它
"""
# 获取数据库中的文章列表
model = Article
# template_name属性用于指定使用哪个模板进行渲染
template_name = 'article.html'
# context_object_name属性用于给上下文变量取名(在模板中使用该名字)
context_object_name = 'article'
def get_object(self):
obj = super(DetailView, self).get_object()
# 设置浏览量增加时间判断,同一篇文章两次浏览超过半小时才重新统计阅览量,作者浏览忽略
u = self.request.user
ses = self.request.session
the_key = 'is_read_{}'.format(obj.id)
is_read_time = ses.get(the_key)
if u != obj.author:
if not is_read_time:
obj.update_views()
ses[the_key] = time.time()
else:
now_time = time.time()
t = now_time - is_read_time
if t > 60 * 30:
obj.update_views()
ses[the_key] = time.time()
# 文章可以使用markdown书写,带格式的文章,像csdn写markdown文章一样
md = markdown.Markdown(extensions=[
'markdown.extensions.extra',
'markdown.extensions.codehilite',
TocExtension(slugify=slugify),
])
obj.body = md.convert(obj.body)
obj.toc = md.toc
return obj
def get_context_data(self, **kwargs):
context = super(DetailView, self).get_context_data(**kwargs)
context['category'] = self.object.id
return context
blog -> storm -> urls.py
# ---------------------------
__author__='stormsha'
__date__='2019/3/10 21:03'
# ---------------------------
from django.conf.urls import url
from .views import IndexView, DetailView
urlpatterns = [
# 首页
url(r'^$', IndexView.as_view(template_name='index.html'), name='index'), # 主页,自然排序
# 给我留言
url(r'^category/message/$', MessageView, name='message'),
# 关于自己
url(r'^category/about/$', AboutView, name='about'),
# 赞助作者
url(r'^category/donate/$', DonateView, name='donate'),
# 技术交流
url(r'^category/exchange/$', ExchangeView, name='exchange'),
# 项目合作
url(r'^category/project/$', ProjectView, name='project'),
# 提问交流
url(r'^category/question/$', QuestionView, name='question'),
# 分类页面
url(r'^category/(?P<bigslug>.*?)/(?P<slug>.*?)', IndexView.as_view(template_name='content.html'), name='category'),
# 归档页面
url(r'^date/(?P<year>\d+)/(?P<month>\d+)/$', IndexView.as_view(template_name='archive.html'), name='date'),
# 标签页面
url(r'^tag/(?P<tag>.*?)/$', IndexView.as_view(template_name='content.html'), name='tag'),
# 文章详情页面
url(r'^article/(?P<slug>.*?)/$', DetailView.as_view(), name='article'),
]
新添加的路由
url(r'^article/(?P<slug>.*?)/$', DetailView.as_view(), name='article'),
首页模板文章列表部分代码
<!--文章导航条-->
<header>
<!--lower 统一英文字符为小写-->
<a class="label label-important" href="/category/{{ article.category.bigcategory.name }}/{{ article.category.name|lower }}">{{ article.category.name }}<i class="label-arrow"></i>
</a>
<!--文章标题-->
<h2>
<a target="_blank" href="/article/{{ article.slug }}" title="{{ article.title }}">{{ article.title }} </a>
</h2>
</header>
<!--文章缩略图-->
<div class="focus">
<a target="_blank" href="/article/{{ article.slug }}"><img class="thumb" width="200" height="123" src="{{ article.img_link }}" alt="{{ article.title }}"/>
</a>
</div>
前端请求的路径,带一个文章slug参数、slug是文章的唯一标识符,也称作文章别名,别问有啥用,就是提升逼格
/article/{{ article.slug }}
详情页模板
这里只展示部分代码做说明,源码参照Github
blog -> templates -> article.html
<article class="article-content">
# 文章内容,safe过滤器,把文章中带的标签转换成浏览器可解析的编码
{{ article.body|safe }}
<p>转载请注明:
<a href="{% url 'blog:article' object.slug %}">StormSha</a> »
<a href="{% url 'blog:article' object.slug %}">{{ object.title }}</a>
</p>
</article>
object: 是通用基类方法get_object返回的文章详情对象
推荐阅读:通用基类
2、实现博客的上一篇与下一篇功能
为了实现这个功能,我们需要在templatetags中获取该篇博客的上一篇博客以及下一篇博客。为了实现这个功能,我们需要考虑到以下2种情况:
博客的id号有可能是不连续的,当我们删除一篇博客时,连带着该id号一块删除了,如果通过blog_id - 1和blog_id+1来获取博客的上一篇与下一篇,则有可能会出错。如果是第一篇博客,它是没有上一篇的;同样,最后一篇博客也是没有下一篇的 因此,我们可以使用状态码has_prev和has_next来判断博客是否有上一篇和下一篇,并通过对id进行循环来判断id号码的连续性,实现代码如下:
blog -> templatetags -> blog_tags.py
# 获取前一篇文章,参数当前文章 ID
@register.simple_tag
def get_article_previous(article_id):
has_previous = False
id_previous = int(article_id)
while not has_previous and id_previous >= 1:
article_previous = Article.objects.filter(id=id_previous - 1).first()
if not article_previous:
id_previous -= 1
else:
has_previous = True
if has_previous:
article = Article.objects.filter(id=id_previous).first()
return article
else:
return
# 获取下一篇文章,参数当前文章 ID
@register.simple_tag
def get_article_next(article_id):
has_next = False
id_next = int(article_id)
article_id_max = Article.objects.all().order_by('-id').first()
id_max = article_id_max.id
while not has_next and id_next <= id_max:
article_next = Article.objects.filter(id=id_next + 1).first()
if not article_next:
id_next += 1
else:
has_next = True
if has_next:
article = Article.objects.filter(id=id_next).first()
return article
else:
return
blog -> templates -> article.html
<nav class="article-nav">
<span class="article-nav-prev">
<i class="fa fa-angle-double-left"></i>
{% get_article_previous object.id as article_previous %}
<a href="{% url 'blog:article' article_previous.slug %}" rel="prev">{{ article_previous.title }}</a>
</span>
<span class="article-nav-next">
{% get_article_next object.id as article_next %}
<a href="{% url 'blog:article' article_next.slug %}" rel="prev">{{ article_next.title }}</a>
<i class="fa fa-angle-double-right"></i>
</span>
</nav>
如此,即可实现博客的上一篇与下一篇功能。
{% include 'comment_list.html' %}
源码详情页中的评论功能,再用户注册、登录、修改个人中心后讲解,重要的留在最后
【友情提示】——如果发现有表达错误,或者知识点错误,或者搞不懂的地方,请及时留言,可以在评论区互相帮助,让后来者少走弯路是我的初衷。我也是一步步摸着石头走过来的,深知网络上只言片语的图文教程,给初学者带来的深深困扰。
【建议】——在对项目结构不太熟悉时,参照完整源码少走弯路
转载请注明: StormSha » Django个人博客开发十二 | 博客详情页面