Django 博客
来源:互联网 发布:java socket编程 代码 编辑:程序博客网 时间:2024/06/08 14:41
前言
一般博客主页都有侧边栏,分别有阅读排行、文章分类和文章存档等栏目,可以在视图函数将这些内容传递给模板,在模板里展示
如果在另一个页面也要显示这些栏目,就会造成很多重复代码。可以使用自定义模板标签来减少这些重复,同时也不用改变已有的视图函数
自定义模板标签
新建blog/templatetags
目录,创建post_tags.py
,文件名随意
在post_tags.py
里添加
from django import templateregister = template.Library()
例如要添加一个显示最近五篇文章的栏目,只要用register.simple_tag
装饰我们的函数
@register.simple_tagdef get_recent_post(): return Post.objects.all()[:5]
由于Post
模型默认按照创建时间降序,所以只需取前5篇就可以了
在模板文件里,需要使用load
标签通过文件名加载自定义标签{% load post_tags %}
接着就能用{% get_recent_post as recent_post %}
来获取最近文章列表了
{% load post_tags %}{% get_recent_post as recent_post %}<ul> {% for p in recent_post %} <li><a href="{{ p.get_absolute_url }}">{{ p.title }}</a></li> {% endfor %}</ul>
有不明白的可以看自定义模板标签的官方文档
文章分类
编写标签函数
@register.simple_tagdef get_categories(): return Category.objects.all()
在模板里引用
{% get_categories as categories %}<ul> <li>文章分类</li> {% for category in categories %} <li><a href="{{ category.get_absolute_url }}">{{ category.name }} ({{ category.post_set.count }})</a> </li> {% endfor %}</ul>
为了方便获取Category
的url
,在Category
添加一个get_absolute_url
方法
def get_absolute_url(self): return '%s#%s' % (reverse('blog:category'), self.name)
只是简单的在blog:category
的url
加上#名字
,这样就可以通过http://127.0.0.1/category/#名字
跳转到对应的分类
阅读排行
Post
模型已经有views
字段了,但是没引用。我们需要在每次浏览器浏览对应文章的时候在views
变量加1
可以通过在详情视图的get
方法里对views
变量加1,并保持到数据库里
首先在Post
模型新增increase_views
方法
def increase_views(self): self.views += 1 self.save(update_fields=['views'])
blog/views.py
的PostView
里覆写def get(self, request, *args, **kwargs)
方法
这个get
方法在父类BaseDetailView
中
class BaseDetailView(SingleObjectMixin, View): """ A base view for displaying a single object """ def get(self, request, *args, **kwargs): self.object = self.get_object() context = self.get_context_data(object=self.object) return self.render_to_response(context)
BaseDetailView
的get
方法做了三个动作
通过get_object
方法获取当前的模型对象,我们的应用里对应的就是一篇文章
通过get_context_data
方法获取当前模板上下文
通过render_to_response
渲染模板
所以在PostView
里,覆写get
方法,先调用父类的get
方法就能获取当前的Post
实例self.object
,然后调用increase_views
方法
def get(self, request, *args, **kwargs): response = super(PostView, self).get(request, *args, **kwargs) self.object.increase_views() return response
这样每次访问都会增加访问数了
接下来在blog/templatetags/post_tags.py
添加一个新的模板标签get_most_read_post
,这次可以传递一个参数num
,可以在模板里传入,默认是5篇,只需要将Post
按views
的降序排序返回指定数量就完成了
@register.simple_tagdef get_most_read_post(num=5): return Post.objects.all().order_by('-views')[:num]
在模板里可以这么使用
{% get_most_read_post 10 as most_read_post %}<ul> <li>阅读排行</li> {% for p in most_read_post %} <li><a href="{{ p.get_absolute_url }}">{{ p.title }} ({{ p.views }})</a></li> {% endfor %}</ul>
标签
和Category
模型一样,Tag
模型也添加一个get_absolute_url
方法
def get_absolute_url(self): return '%s#%s' % (reverse('blog:tag'), self.name)
在blog/templatetags/post_tags.py
添加一个新的模板标签get_tags
from django.db.models import Count@register.simple_tagdef get_tags(): return Tag.objects.annotate(post_num=Count('post')).filter(post_num__gt=0)
这里过滤掉文章数量为0的标签,由于Tag
和Post
是多对多关系,可以通过len(tag.post_set.all())
来获取每个Tag
下Post
的数量,但是这样太麻烦了,可以通过annotate
方法,直接对Post
计数,添加一个post_num
属性,然后通过filter
方法进行过滤
annotate
的详细使用方法请查看官方文档
和上面的其他自定义标签一样,在模板中可以这样使用
{% get_tags as tags %}<ul> <li>标签</li> <li><p> {% for tag in tags %} <a href="{{ tag.get_absolute_url }}">{{ tag.name }}</a> {% endfor %} </p></li></ul>
文章存档
在blog/templatetags/post_tags.py
添加一个新的模板标签get_posts
@register.simple_tagdef get_posts(num=None): return Post.objects.all()[:num]
在模板中显示时,也要和上一篇文章所讲的归档页面一样,需要通过regroup
标签对文章依次按年和月进行重新分组,这里并不需要显示每一篇的标题,只是显示有发布文章的年份月份和对应的文章数量,通过month.list|length
来获取每个具体年月的文章数量
<ul> <li>文章存档</li> {% get_posts as posts %} {% regroup posts by created_time.year as posts_by_year %} {% for year in posts_by_year %} {% regroup year.list by created_time.month as posts_by_month %} {% for month in posts_by_month %} <li><a href="{% url 'blog:archive' %}# {{ year.grouper }}{{ month.grouper|stringformat:'02d' }}">{{ year.grouper }}年{{ month.grouper }}月 ({{ month.list|length }})</a></li> {% endfor %} {% endfor %}</ul>
这里的每一项的href
中的url
,都是用'blog:archive'
对应的路径加上#年月
组成,月份使用了一个模板过滤器stringformat:'02d'
,使得单个数字的月份会在前面补0,当然了,在archive
页面也需要这么处理,才能正确跳转
本文相关源码
- Django 博客
- Django 博客
- Django 博客
- Django 博客
- Django 博客
- Django 博客
- Django 博客
- Django 博客
- Django 博客
- Django 博客
- Django--博客
- django搭建简易博客
- django创建博客
- django 博客一
- django博客二
- django博客三
- django博客四
- Zinnia - Django 博客框架
- HDU-2102 A计划(BFS)
- 想不想制作一个Coreldraw 蝴蝶结呀这个是非常详细的教程
- 对象与类 章节四
- SystemServer进程源码分析
- 文本分类需要CNN?No!fastText完美解决你的需求(后篇)
- Django 博客
- RelativeLayout的几个关键属性
- 图片上传以及允许连续上传同一图片
- [MySQL]事务和ACID原则
- string类------新标准c++程序设计
- 函数
- TensorFlow系列教程(4)---手写字体识别
- 嵌入式& 操作系统概述
- 进程管理