创建自定义的模版标签
自定义的模板标签 主要用于在每一个页面上都需要来显示,这样就方便了使用,而不需要在每一个views函数中render。
django提供了以下函数以简单的方式创建自己的模板标签:
- simple_tag(简单标签):处理数据并返回一个字符串(string)
- inclusion_tag(包含标签):处理数据并返回一个渲染过的模板(template)
- assignment_tag(分配标签):处理数据并在上下文(context)中设置一个变量(variable)
进入blog 应用文件夹:
blog/
__init__.py
models.py
...
templatetags/ #新创建文件夹,设置成python packages
__init__.py
blog_tags.py
simple_tag的使用在blog_tags中键入代码
from django import template # 导入django中的模板文件
from blog.models import Post
register = template.Library() # 注册
@register.simple_tag #使用装饰器函数定义此函数为一个简单标签(tag)并注册它
def total_posts():
return Post.objects.all().count() #返回字符串
Django将会使用这个函数名作为标签(tag)名。如果你想使用别的名字来注册这个标签(tag),你可以指定装饰器的name属性,比如@register.simple_tag(name='my_tag')。
在模板中使用方法
{%load blog_tags %} #加载 blog_tags文件
This is my blog. I've written {% total_posts %} posts so far.
#使用{% total_posts %}模板变量,返回一个字符串
inclusion_tag的使用:在blog_tags文件中键入
@register.inclusion_tag('blog/post/latest_post.html') # 必须指定渲染的模板是哪个
def show_latest_tag(count=5):
latest_posts = Post.objects.all().order_by('-publish')[:count]
return {'latest_posts': latest_posts} # 必须返回一个字典
在指定渲染的html中
{% for post in latest_posts %}
-
{{ post.title }}
{% endfor %}
在base.html中增加,注:可以通过传入可选的评论数量值来使用显示,类似{% show_latest_posts 3 %}。
assigment_tag的使用
分配标签(assignment tag)类似简单标签(simple tags)但是他们将结果存储在给予的变量中。
from django.db.models import Count
@register.assignment_tag
def get_most_commented_posts(count=5):
return Post.published.annotate(
total_comments=Count('comments')
).order_by('-total_comments')[:count]
为Post模型中的每一个实例添加total_comments字段,此字段计算Comment模型中关联别名comments中的数量,再进行order_by排序
这个查询集(QuerySet)使用annotate()函数,为了进行聚合查询,使用了Count聚合函数。我们构建了一个查询集(QuerySet),聚合了每一个帖子的评论总数并保存在total_comments字段中,接着我们通过这个字段对查询集(QuerySet)进行排序。我们还提供了一个可选的count变量,通过给定的值来限制返回的帖子数量。
除了Count以外,Django还提供了不少聚合函数,例如Avg,Max,Min,Sum.你可以在 https://docs.djangoproject.com/en/1.8/topics/db/aggregation/ 页面读到更多关于聚合方法的信息。
在base.html中侧边栏添加
Most commented posts
{% get_most_commented_posts as most_commented_posts %}
{% for post in most_commented_posts %}
-
{{ post.title }}
{% endfor %}
使用分配模板标签(assignment template tags)的方法是{% template_tag as variable %}。对于我们的模板标签(template tag)来说,我们使用{% get_most_commented_posts as most_commented_posts %}。 这样,我们可以存储这个模板标签(template tag)返回的结果到一个新的名为most_commented_posts变量中。之后,我们就可以用一个无序列表(unordered list)显示返回的帖子。
创建自定义的模板过滤器(template filters)
创建一个自定义的过滤器(filter),可以在我们的blog帖子中使用markdown语法,然后在模板(template)中将帖子内容转变为HTML。Markdown是一种非常容易使用的文本格式化语法并且它可以转变为HTML。
1.先安装markdown
pip3 install markdown
编辑blog_tags文件
from django.utils.safestring import mark_safe
import markdown
@register.filter(name='markdown')
def markdown_format(text):
return mark_safe(markdown.markdown(text))
设定了过滤器,并名字为'markdown',为了避免与模板名起冲突,过滤函数取名为markdown_format,使用mark_safe来标记结果,正常情况下django不会依赖任何html代码并转义,除非mark_safe。
在templates中使用
{% load blog_tags %}
{{ post.body|markdown}}
#{{ post.body|truncateword:300|linebreaks }}
{{ post.body|truncateword_html:30 }}#truncateword_html过滤器(filter)会在一定数量的单词后截断字符串,避免没有关闭的HTML标签(tags)。
为你的站点添加一个站点地图(sitemap)
Django自带一个站点地图(sitemap)框架,允许你为你的站点动态生成站点地图(sitemap)。一个站点地图(sitemap)是一个xml文件,它会告诉搜索引擎你的网站中存在的页面,它们的关联和它们更新的频率。使用站点地图(sitemap),你可以帮助网络爬虫(crawlers)来对你的网站内容进行索引和标记。
Django站点地图(sitemap)框架依赖django.contrib.sites模块,这个模块允许你将对象和正在你项目运行的特殊网址关联起来。当你想用一个单独Django项目运行多个网站时,这是非常方便的。
SITE_ID = 1 #添加
# Application definition
INSTALLED_APPS = (
# ...
'django.contrib.sites',#添加
'django.contrib.sitemaps',#添加
)
创建表python3 manage.py makemigrations
python3 manage.py migrate
sites应用现在已经在数据库中进行了同步。现在,在你的blog应用目录下创建一个新的文件命名为sitemaps.py
from django.contrib.sitemaps import Sitemap
from .models import Post
class PostSitmap(Sitemap): # 通过继承Sitemap类可以创建一个自定义的站点地图
changefrep = 'weekly' # 页面修改频率
priority = '0,9' # 网站中的关联性(优先级)
def items(self):
return Post.objects.all() # items()方法返回了在这个站点地图(sitemap)中所包含对象的查询集(QuerySet)
def lastmod(self,obj):
return obj.publish # lastmode方法接收items()返回的每一个对象并且返回对象的最后修改时间
可以在Django的官方文档 https://docs.djangoproject.com/en/1.8/ref/contrib/sitemaps/ 页面中获取更多的站点地图(sitemap)参考
在主urls文件中新增
from django.contrib.sitemaps.views import sitemap#导入sitemap视图
from blog.sitemaps import PostSitmap #导入自定义的sitemap类
sitemaps = {
'posts':PostSitmap
}
urlpatterns = [
url(r'^admin/', include(admin.site.urls)),
url(r'^blog/', include('blog.urls', namespace='blog', app_name='blog')),
url(r'^sitemap\.xml$', sitemap, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap'),#新增
]
打开http://127.0.0.1:8000/sitemap.xml显示xml
为你的blog帖子创建feeds
Django有一个内置的syndication feed框架,就像用sites框架创建站点地图(sitemap)一样,使用类似的方式(manner),你可以动态(dynamically)生成RSS或者Atom feeds。
在blog应用的目录下创建一个新文件命名为feeds.py。添加如下代码:
from django.contrib.syndication.views import Feed # 从django.普通.联合.视图 导入Feed类
from django.template.defaultfilters import truncatewords # 导入 truncatechars
from .models import Post
class LatestPostsFeed(Feed):
title = 'My blog' # 标题
link = '/blog/' # 连接
description = 'New posts of my Blog' # 描述
def items(self):
return Post.objects.all()[:5] # 返回前5个
def item_title(self, item):
return item.title # 返回对象的title
def item_description(self, item): # 返回描述
return truncatewords(item.body, 30) # 文章的前30个单词
首先,我们继承了syndication框架的Feed类创建了一个子类。其中的title,link,description属性各自对应RSS中的
items()方法返回包含在feed中的对象。我们只给这个feed取回最新五个已发布的帖子。item_title()和item_description()方法接受items()返回的每个对象然后返回每个item各自的标题和描述信息。我们使用内置的truncatewords模板过滤器(template filter)构建帖子的描述信息并只保留最前面的30个单词。
现在,编辑blog应用下的urls.py文件,导入你刚创建的LatestPostsFeed,在新的URL模式(pattern)中实例化feed:
from .feeds import LatestPostsFeed
urlpatterns = [
# ...
url(r'^feed/$', LatestPostsFeed(), name='post_feed'),
]
在浏览器中转到 http://127.0.0.1:8000/blog/feed/ 。你会看到最新的5个blog帖子的RSS feedincluding:
最后一步是在blog的侧边栏(sitebar)添加一个feed订阅(subscription)链接。打开blog/base.html模板(template),在侧边栏(sitebar)的div中的帖子总数下添加如下代码:
学习来源于夜夜月翻译的django by example