第三章内容:
- 创建自定义模板标签和过滤器,
- 添加网站地图和帖子提要,
- 利用PostgreSQL实现全文本搜索。
我自己补充点内容:
之前博客一直没有样式,侧边栏也没正确显示,我自己搜了下,来完成这个。当然依旧不会很好看。在项目settings.py 中加入:
STATICFILES_DIRS = [(os.path.join(BASE_DIR, 'static'))]
然后新建static文件夹,下面建css文件夹新建文件blog.css,写入:
#content{float: left;width:800px;height: 150px;}
#sidebar{border-left: 1px solid #e1e1e1;float: right;width: 384px;}
3.1 创建自定义模板标签和过滤器
创建templatetags文件,添加__init__.py,再建blog_tags.py,填写代码:
from django import template
from ..models import Post
register = template.Library()
@register.simple_tag # 注册为简单的标签
def total_posts():
return Post.published.count()
在blog/templates/base.html中添加:
一个在上面,一个在下面,自己调整位置。
{% load blog_tags %}
<p>This is my blog.I've written {% total_posts %} posts so far.</p>
可以运行项目查看一下,
在blog_tags.py写下列代码:
@register.inclusion_tag('blog/post/latest_posts.html')
def show_latest_posts(count=5):
latest_posts = Post.published.order_by('-publish')[:count]
return {'latest_posts': latest_posts}
然后再blog/post/latest_posts.html写代码:
<ul>
{% for post in latest_posts %}
<li>
<a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
</li>
{% endfor %}
</ul>
侧栏base.html:
<h3>Latest posts</h3>
{% show_latest_posts 3 %}
在blog_tags.py写下列代码:
@register.simple_tag
def get_most_commented_posts(count=5):
return Post.published.annotate(
total_comments=Count('comments')
).order_by('-total_comments')[:count]
侧栏base.html下面加入:
<h3>Most commented posts</h3>
{% get_most_commented_posts as most_commented_posts %}
<ul>
{% for post in most_commented_posts %}
<li>
<a href="{{ post.get_absolute_url }}">{{ post.title }}</a>
</li>
{% endfor %}
</ul>
django 包含了各种内建模板过滤器,并可调整模板中的变量。
这里我们创建一个自定义过滤器,使用markdown语法,将帖子内容转化为html.
pip install Markdown==2.6.11
在blog_tags.py文件中加入代码:
import markdown
from django.utils.safestring import mark_safe
@register.filter(name='markdown')
def markdown_format(text):
return mark_safe(markdown.markdown(text))
在blog/post/list.html和blog/post/detail.html中extend下面加这个:
{% load blog_tags %}
detail.html中上面那个修改为下面的:
<!--{{ post.body|linebreaks }}-->
{{ post.body|markdown }}
list.html中上面那个修改为下面的:
<!--{{ post.body|truncatewords:30|linebreaks }}-->
{{ post.body|markdown|truncatewords:30| }}
在浏览器输入http://127.0.0.1:8000/admin/blog/post/add/添加下面内容
This is a post formatted with markdown
---------------------------------------------
*This is emphasized* and **this is more emphasized**.
Here is a list:
*One
*Two
*Three
And a [link to the Django website](https://www.djangoproject.com/)
打开博客页面可以看到显示方式有了变化。
3.2 向站点添加网站地图
dango 中包含了网站地图框架,进而可动态生成网站地图。
编辑主项目settings.py文件:
SITE_ID = 1
INSTALLED_APPS = [
...
'django.contrib.sites',
'django.contrib.sitemaps',
]
执行迁移
python manage.py migrate
sites应用程序将与数据库同步,在blog文件夹下创建sitemaps.py,添加代码:
from django.contrib.sitemaps import Sitemap
from blog.models import Post
class PostSitemap(Sitemap): # 继承Sitemap生成自定义网站地图
changefreq = 'weekly' # 页面变化频率
priority = 0.9
def items(self): # 网站地图对象的QuerySet
return Post.published.all()
def lastmod(self, obj): # 检索items()返回的各个对象,返回最近修改时间
return obj.updated
配置主项目的urls.py,这里我贴出完整的代码:
from django.contrib import admin
from django.contrib.sitemaps.views import sitemap
from django.urls import path, include
from sitemaps import PostSitemap
sitemaps = {
'posts': PostSitemap,
}
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include(('blog.urls', 'blog'), namespace='blog')),
path('sitemap.xml/', sitemap, {'sitemaps': sitemaps}, name='django.contrib.sitemaps.views.sitemap'),
]
访问:http://127.0.0.1:8000/sitemap.xml/
AttributeError at /sitemap.xml/
'Post' object has no attribute 'updated'
我的这里报错了,不知道怎么解决,大佬知道的话,告诉我下,我先把那个注释掉:
#def lastmod(self, obj): # 检索items()返回的各个对象,返回最近修改时间
#return obj.updated
3.3 创建帖子提要
django 包含了一个内建聚合提要(feed)框架,可据此动态生成RSS或Atom提要。
title,link,description对应RSS元素。
blog下创建feeds.py文件添加下列代码:
from django.contrib.syndication.views import Feed
from django.template.defaultfilters import truncatewords
from blog.models import Post
class LatestPostsFeed(Feed):
title = 'My blog'
link = '/blog/'
description = 'New posts of my blog.'
def items(self):
return Post.published.all()[:5]
def item_title(self, item): # 获取条目标题
return item.title
def item_description(self, item): # 获取条目描述
#使用truncatewords内建模板过滤器构建博客帖子的描述内容(30个单词)。
return truncatewords(item.body, 30)
访问http://127.0.0.1:8000/blog/feed/可以看到下面内容。