利用Django实现的功能如下:
- Post模型增加保存时生成摘要功能
- views的视图函数改为视图类
- 优化评论显示页面
- 增加页面分页功能
具体实现过程如下:
1.Post模型增加保存时生成摘要功能
在模型保存时,自定义一些功能,此时我们不能重写__init__,应该利用save()进行自定义的初始化操作。在Post模型中,我们需要有能自动生成摘要的功能,以便于在博客列表中显示部分摘要。
...
import markdown
from django.utils.html import strip_tags
class Post(models.Model):
...
def save(self, *args, **kwargs):
if not self.excerpt:
md = markdown.Markdown(extensions=[
'markdown.extensions.extra',
'markdown.extensions.codehilite',
])
self.excerpt = strip_tags(md.convert(self.body)[:20])
#继承并重写save函数
super(Post, self).save(*args, **kwargs)
class Meta:
#帖子返回时的排序方式,按时间倒序排。
ordering = ['-created_time']
2.把视图函数改为视图类:
视图类继承了ListView和DetailView等类。与视图函数相比,视图类的代码更简洁方便,并带有许多使用的功能。我们只需要继承相应的功能,然后重写方法,添上我们自定义的内容即可。
...
from .models import Post, Category
from django.views.generic import ListView, DetailView
from comments.forms import CommentForm
class IndexView(ListView):
model = Post
template_name = 'blog/index.html'
context_object_name = 'post_list'
paginate_by = 1
class PostDetailView(DetailView):
model = Post
template_name = 'blog/detail.html'
#上下文环境对象命名为post,方便在模板中使用
context_object_name = 'post'
#继承父类的get,并增加访问量加1的功能
def get(self, request, *args, **kwargs):
response = super(PostDetailView, self).get(request, *args, **kwargs)
self.object.increase_views()
return response
#继承父类的get_object,同时对post.body进行markdown处理
def get_object(self, queryset=None):
post = super(PostDetailView, self).get_object(queryset=None)
post.body = markdown.markdown(post.body, extensions=[
'markdown.extensions.extra',
'markdown.extensions.codehilite',
'markdown.extensions.toc',])
return post
#继承父类的get_context_data,并增加form,comment_list到上下文数据context中,这些数据将会在模板中使用
def get_context_data(self, **kwargs):
context = super(PostDetailView, self).get_context_data(**kwargs)
form = CommentForm()
comment_list = self.object.comment_set.all()
context.update(
{
'form':form,
'comment_list':comment_list
}
)
return context
def archives(request, year, month):
post_list = Post.objects.filter(created_time__year=year,
created_time__month=month).order_by('-created_time')
return render(request, 'blog/index.html', context={'post_list':post_list})
class CategoryView(ListView):
model = Post
template_name = 'blog/index.html'
context_object_name = 'post_list'
def get_queryset(self):
cate = get_object_or_404(Category, pk=self.kwargs.get('pk'))
#返回当前category对象所对应的post
return super(CategoryView,self).get_queryset().filter(category=cate).order_by('-created_time')
urls.py的修改:
在views的视图改为视图函数后,相应的url也需要做更改,具体如下:
from django.conf.urls import url,include
from django.contrib import admin
from . import views
app_name = 'blog'
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^(?P<pk>[0-9]+)/$', views.PostDetailView.as_view(), name='detail'),
url(r'^archives/(?P<year>[0-9]{4})/(?P<month>[0-9]{1,2})/$', views.archives, name='archives'),
url(r'^category/(?P<pk>[0-9]+)/$', views.CategoryView.as_view(), name='category'),
]
3.优化评论页面:
模板修改,评论的显示页面得到优化。
...
<div class="comment-list-panel">
<h3>评论列表,共 <span>{{ post.comment_set.count }}</span> 条评论</h3>
<ul class="comment-list list-unstyled">
{% for comment in comment_list %}
<li class="comment-item">
<span class="nickname">{{ comment.name }}</span>
<time class="submit-date"
datetime="{{ comment.created_time }}">{{ comment.created_time }}</time>
<div class="text">
{{ comment.text }}
</div>
</li>
{% empty %}
暂无评论
{% endfor %}
</ul>
</div>
...
4.添加分页功能:
在views中重写get_context_data()方法,并添加自定义方法pagination_data()。
class IndexView(ListView):
model = Post
template_name = 'blog/index.html'
context_object_name = 'post_list'
#每个分页只有1帖子个内容
paginate_by = 1
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
#获得分页的相关数据
paginator = context.get('paginator')
page = context.get('page_obj')
is_paginated = context.get('is_paginated')
#把分页的相关数据传入方法中,获得处理后的分页数据
pagination_data = self.pagination_data(paginator, page, is_paginated)
#分页数据更新到上下文环境中
context.update(pagination_data)
return context
def pagination_data(self, paginator, page, is_paginated):
if not is_paginated:
return {}
left = []
right = []
left_has_more = False
right_has_more = False
first = False
last = False
page_number = page.number
total_pages = paginator.num_pages
page_range = paginator.page_range
if page_number ==1:
right = page_range[page_number:page_number + 2]
if right[-1] < total_pages -1:
right_has_more = True
if right[-1] <total_pages:
last = True
elif page_number == total_pages:
left = page_range[(page_number-3) if(page_number - 3) > 0 else 0:page_number -1]
if left[0] > 2:
left_has_more = True
if left[0] > 1:
first = True
else:
left = page_range[(page_number-3) if (page_number-3) > 0 else 0: page_number-1]
right = page_range[page_number:page_number+2]
if right[-1] < total_pages -1:
right_has_more = True
if right[-1] < total_pages:
last = True
if left[0] > 2:
left_has_more = True
if left[0] > 1:
first = True
data = {
'left':left,
'right':right,
'left_has_more':left_has_more,
'right_has_more':right_has_more,
'first':first,
'last':last,
}
return data
在index.html中添加分页功能的模板内容,具体如下:
{% if is_paginated %}
<div class="pagination">
<ul>
{% if first %}
<li><a href="?page=1">1</a></li>
{% endif %}
{% if left %}
{% if left_has_more %}
<li><span>...</span></li>
{% endif %}
{% for i in left %}
<li><a href="?page={{ i }}">{{ i }}</a></li>
{% endfor %}
{% endif %}
<li class="current"><a href="?page={{ page_obj.number }}">{{ page_obj.number }}</a></li>
{% if right %}
{% for i in right %}
<li><a href="?page={{ i }}">{{ i }}</a></li>
{% endfor %}
{% if right_has_more %}
<li><span>...</span></li>
{% endif %}
{% endif %}
{% if last %}
<li><a href="?page={{ paginator.num_pages }}">{{ paginator.num_pages }}</a></li>
{% endif %}
</ul>
</div>
{% endif %}
摘要的页面显示效果: