经过前面的过程,这个博客的基本功能框架已经差不多了,下面主要本着用户体验的原则增加一些方便使用的小功能。这一节就来实现归档、标签分类、aboutme和分页这四个功能。
归档
归档就是列出当前博客里面的所有已发表文章,并且能够显示发布时间。
首先,在base.html里面增加一个归档按钮,位置参照其他按钮:
<li class="active"><a href="{% url 'archives' %}">归档</a></li>
然后,在mysite\mysite\urls.py添加一条url:
url(r'^archives/$', views.archives, name='archives'),
接着,在views.py增加一个视图逻辑:
from django.http import Http404
def archives(request):
try:
post_list = Article.objects.all().filter(published_date__isnull=False).order_by('-published_date')
except Article.DoesNotExist:
raise Http404
return render(request, 'blog/archives.html', {'post_list': post_list, 'error': False})
最后,在mysite\templates\blog增加一个模板archives.html:
{% extends "blog/base.html" %}
{% block content %}
<div class="posts">
<ul>
{% for post in post_list %}
<li>
<div class="date">{{ post.published_date |date:'M d, Y'}}</div>
<header class="post-header">
<h5 class="post-title"><a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h5>
</header>
</li>
{% endfor %}
</ul>
</div>
{% endblock %}
标签分类
标签分类就是点击对应的标签按钮, 会跳转到一个新的页面,这个页面是所有相关标签的文章的罗列。
回顾一下,有标签的地方包括主页面和详情页面。因此第一步就是在这两个地方的标签设置链接,把下面:
<a class="post-category post-category-js" href="#">{{ post.category }}</a>
改成下面:
{% 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 %}
这里还使用了if的原因是为了防止有的文章没有标签会出错。
第二步就是在mysite\mysite\urls.py添加一条url:
url(r'^tag(?P<tag>\w+)/$', views.search_tag, name='search_tag'),
第三条是增加视图:
def search_tag(request, tag):
try:
post_list = Article.objects.filter(category__iexact=tag).filter(published_date__isnull=False).order_by('-published_date')
except Article.DoesNotExist:
raise Http404
return render(request, 'blog/tag.html', {'post_list' : post_list})
第四步是增加模板tag.html:
{% extends "blog/base.html" %}
{% block content %}
<div class="blog-post">
{% for post in post_list %}
<div class="date">
{{ post.published_date |date:'M d, Y'}}
</div>
<h3 class="blog-post-title"><a href="{% url 'post_detail' pk=post.pk %}">{{ post.title }}</a></h3>
<p>
<a class="post-category post-category-js" href="{% url 'search_tag' tag=post.category %}">{{ post.category|title }}</a>
</p>
<p>{{ post.text|linebreaks }}</p>
<br />
{% endfor %}
</div>
{% endblock %}
AboutMe
这个就更没什么技术含量了。
base.html里再加一个按钮,现在按钮区域变成这样了:
<div style="float: right">
<ul class="nav nav-pills">
<li class="active"><a href="{% url 'archives' %}"><span class="glyphicon glyphicon-briefcase"></span> 归档</a></li>
<li class="active"><a href="{% url 'post_new' %}"><span class="glyphicon glyphicon-pencil"></span> 新建</a></li>
<li class="active"><a href="{% url 'post_draft_list' %}"><span class="glyphicon glyphicon-th-list"></span> 草稿箱</a></li>
<li class="active"><a href="{% url 'about_me' %}"><span class="glyphicon glyphicon-user"></span> 关于</a></li>
</ul>
</div>
增加urls.py:
url(r'^aboutme/$', views.about_me, name='about_me'),
增加视图views.py:
def about_me(request):
return render(request, 'blog/aboutme.html')
增加模板aboutme.html:
{% extends "blog/base.html" %}
{% block content %}
<div class="posts">
<p> About Me 正在建设中... </p>
</div>
{% endblock %}
这里面就完全发挥个人风格了。
分页
在首页显示文章列表时候需要分页显示,这时候可以使用django内置的Paginator来分页。官方文档:Pagination
只需要修改两处。
第一处,在views.py里面修改post_list逻辑:
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.db.models import Count
from .commons import cache_manager
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')
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)
return render(request, 'blog/post_list.html', {'posts': posts, 'page': True})
第二处,修改post_list.html页面,增加分页div:
{% extends 'blog/base.html' %}
{% block content %}
{% for post in posts %}
... # post循环不变 # ...
{% endfor %}
{% if page %}
<div class="pagination">
<span class="step-links">
{% if posts.has_previous %}
<a href="?page={{ posts.previous_page_number }}">previous</a>
{% endif %}
<span class="current">
Page {{ posts.number }} of {{ posts.paginator.num_pages }}.
</span>
{% if posts.has_next %}
<a href="?page={{ posts.next_page_number }}">next</a>
{% endif %}
</span>
</div>
{% endif %}
{% endblock %}
这里设定每页显示十篇文章,也可以在视图里面修改成其他数量。
这里的分页间的切换只有上一页/下一页以及知道共有多少页,还不能实现任意页切换,因此还是不完善的。因为现在文章还不多,所以只用上一页/下一页切换还没有带来多少不便,等到文章数量多的时候就会有很大不便了。等有空或到时候再修改吧!
11.5 update:
实现分页的任意页切换。
在post_list.html里面修改分页的部分为:
{% if page %}
<div class="pagination">
<span class="step-links">
{% if posts.has_previous %}
<a href="?page={{ posts.previous_page_number }}">上一页</a>
{% endif %}
{% for page_number in posts.paginator.page_range %}
{% ifequal page_number posts.number %}
{{ page_number }}
{% else %}
<a href="?page={{ page_number }}">{{ page_number }}</a>
{% endifequal %}
{% endfor %}
{% if posts.has_next %}
<a href="?page={{ posts.next_page_number }}">下一页</a>
{% endif %}
</span>
</div>
{% endif %}
2016.10.24