BBS项目侧边栏&自定义分页器
侧边栏和注册页面使用了inclusion_tag,自定义分页器使用了模版导入include
此外,因为有一个普通的注册界面和一个模态框实现的注册页面,因此也注册也使用了inclusion_tag(这里不再介绍,感兴趣参考Github上BBS仓库的完整源码)
侧边栏
BBS项目个人站点左侧侧边栏用于展示文章标签、文章分类、日期归档的统计信息。
个人站点主页需要上述展示,文章详情页面也需要侧边栏的这些展示信息。
另外,侧边栏的统计信息的数据来自数据库动态展示,因此考虑使用inclusion_tag
,将样式和数据绑定到一块,然后导入到前端个人站点模版文件blog_base.html
。
最后,个人站点blog.html
和文章详情article_detail.html
两个页面继承个人站点模版文件blog_base.html
。
inclusion_tag定义流程
应用中新建一个名字为 templatetags的文件夹
该文件夹内新建一个mytags.py的文件(文件名自定义)
在该文件内准备如下代码:
from django import template
register = template.Library()
代码
- side_bar函数返回的数据给
side_bar.html
模板文件。 - 然后在前端页面使用标签side_bar,则会将绑定了数据的
side_bar.html
当做局部放在前端页面上。
blog_base.html
{% load mytags %}
{% side_bar username %} # 将username传给side_bar
mytags.py
from django import template
from django.db.models import Count
from django.db.models.functions import TruncMonth
from app01 import models
register = template.Library()
@register.inclusion_tag('side_bar.html', name='side_bar')
def side_bar(username):
user_obj = models.UserInfo.objects.filter(username=username).first()
blog = user_obj.blog
# 标签、分类、归档ORM查询
tag_list = models.Tag.objects.filter(blog=blog).annotate(c=Count('article__pk')).values('pk', 'name', 'c')
category_list = models.Category.objects.filter(blog=blog).annotate(c=Count('article__pk')).values('pk', 'name', 'c')
# 日期归档查询使用django提供的TruncMonth自动按月截取,形成一个虚拟字段用于日期分组
archive_list = models.Article.objects.filter(blog=blog). \
annotate(month=TruncMonth('publish_time')).values('month'). \
annotate(c=Count('pk')).order_by('-month').values('month', 'c')
return locals()
side_bar.html
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">文章标签</h3>
</div>
<div class="panel-body">
{% for tag in tag_list %}
<p><a href="/{{ username }}/tag/{{ tag.pk }}/">{{ tag.name }}({{tag.c}})</a></p>
{% endfor %}
</div>
</div>
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">文章分类</h3>
</div>
<div class="panel-body">
{% for category in category_list %}
<p><a href="/{{username}}/category/{{ category.pk }}">{{ category.name }}({{category.c}})</a></p>
{% endfor %}
</div>
</div>
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">文章归档</h3>
</div>
<div class="panel-body">
{% for archive in archive_list %}
<p><a href="/{{ username }}/archive/{{ archive.month|date:'Y-m' }}/">{{ archive.month|date:'Y年m月' }}({{ archive.c }})</a></p>
{% endfor %}
</div>
</div>
自定义分页器
因为bbs主页和个人站点文章列表都需要使用分页,因此考虑使用模版继承的方式实现代码重用。
后端设置
- CV自定义分页器代码,参考
- 在视图函数中设置(bbs主页视图、文章详情视图两个位置设置方式类似)
# bbs首页的视图函数
def index(request):
article_queryset = models.Article.objects.all()
current_page = request.GET.get('page', 1)
all_count = article_queryset.count()
# 1 传值实例化对象
page_obj = Pagination(current_page=current_page, all_count=all_count)
# 2 直接对总数据进行切片操作
page_queryset = article_queryset[page_obj.start:page_obj.end]
# 3 将page_queryset传递到页面,替换之前的book_queryset
return render(request, 'index.html', locals())
前端模版文件设置
- bbs首页继承跟
base.html
模版文件,并通过模版导入的方式引入局部分页器模版文件mypagination.html
# index.html
{% extends 'base.html' %}
{% block left_content %}
'''侧边栏代码略'''
{% endblock %}
{% block right_content %}
<div class="col-md-9">
'''文章列表代码略'''
{#分页器#}
{% include 'mypagination.html' %}
</div>
{% endblock %}
mypagination.html
内直接模版语法,并借助内置过滤器safe
将自定义分页器渲染到前端页面。
# mypagination.html
<div class="text-center">
{{ page_obj.page_html|safe }}
</div>