页面参数的传递与获取
在上面的教程中,我们已经搭建了一个最最简(jian)单(lou)的博客系统,然而真实世界的博客极少采用单页面形式,一般会有一个列表页面显示文章的概要信息,读者可以通过点击页面链接,在一个单独页面中查看文章的完整内容。
所以,我们需要将上次创建的首页模板修改一下,让其只显示文章的概要(比如前200字和一个省略号,这个大狗就暂时不考虑分词了),然后为文章显示创建一个新的页面模板。
这里还有一个问题,就是参数传递。为了在读者点击首页的链接后能否正确的跳转到文章页面,需要在首页的链接中附加一个文章的ID,那么文章页面如何得到这个ID号呢?Django已经为我们考虑到了这个问题,让我们看一下blog应用的URL配置:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name = 'index'),
url(r'^article/(?P<articleID>[0-9]+)', views.article, name='article')
]
大家可以看到,大狗在原来配置的基础上,又为文章页面增加了一行配置。其中“^”表示字符串的起始,后面的“article”是为了和其他路径相区别,后面括号中的内容是一个正则表达式分组,其中“?P”后面尖括号中的“articleID”是分组名称,"[\d]"中的“d”表示“decimal”,即“十进制数字”,后面的加号表示“一个或多个”,整个正则表达式的意思就是,如果URL中出现“article”字样,并且后面出现一个或多个数字的时候,将这组数字识别为“articleID”。
我们在URL配置中,将匹配上述规则的URL连接到了views.py中的article函数,这个函数还是比较简单的:
def article(reqeust, articleID):
template = loader.get_template('blog/article.html')
article = Article.objects.get(id = articleID)
context = {
'article': article,
}
return HttpResponse(template.render(context, reqeust))
同样,我们在template目录下的blog子目录增加了一个名为"article.html"的页面模板文件,以和视图函数对应:
{% load static %}
<htmL>
<head>
<title>欢迎光临「大狗汪叨叨」</title>
<link rel="stylesheet" type="text/css" href="{% static 'blog/css/style.css' %}">
</head>
<body>
<div style="top:20px;left:20px;position:absolute;">
![]({% static 'blog/images/logo.jpeg' %})
</div>
<div style="top:20px;left:200px;position:absolute;">
<span class="pageTitle">大狗汪叨叨</span>
</div>
<div style="left:20px;top:150px;position:absolute;width:600px;background-color:#FFFFFF;padding:20px;">
<h2 class="articleTitle">{{article.title}}</h2>
<p class="articleAuthor">by: {{article.author}} {{article.timestamp}}</p>
<span class="articleBody">{{article.body|linebreaks}}</span>
</div>
</body>
</html>
大狗只是在原来index.html的基础上改了改,后面大狗会抽出时间为页面模板文件润色的,大家放心哈~
接下来,我们还需要对首页页面模板index.html进行一些修改,首先,是将显示文章全文改为显示前200字,大狗本来现在模型类中再加一个函数的,结果一查文档,发现Django内置了这个功能,只需要在页面模板中在占位符后面添加“|truncatewords:200”就可以了(如果是HTML文本,请使用truncatewords_html),然后...然后就发现根本没用,汪嘞个嗷的!又查了下文档,才发现这个是针对英文的,好吧,换成了slice,好使了。然后在概要后面加上三个点点,和一个超链接,就像这样:
{% for article in all_articles %}
<h2 class="articleTitle">{{article.title}}</h2>
<p class="articleAuthor">by: {{article.author}} {{article.timestamp}}</p>
<span class="articleBody">{{article.body|slice:'200'}}...</span>
<br/>
<a href="article/{{article.id}}">查看全文</a>
{% endfor %}
现在,让我们把开发服务器跑起来,看看效果吧:
点击“查看全文”链接后,在单独的页面中显示全文:
显示全文看上去还不错(妹纸从边上经过,不屑的说“这个丑爆了好吗?没有导航栏没有回到首页链接没有页脚,弱爆了好吗?”)好吧,大狗只是验证一下页面参数传递,至于布局,我会抽出时间改的,我保证!
分页?很简单
离大狗上班还有一些时间,我们再给博客首页添加一个必要的功能:分页。
而Django用Paginator类提供了标准的分页功能,大大减少了我们的编码量。
首先,我们需要在URL配置文件中增加首页相关的配置:
from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name = 'index'),
url(r'^(?P<pageNo>[\d]+)',views.indexInPages, name = 'indexInPages'),
url(r'^article/(?P<articleID>[\d]+)', views.article, name='article'),
]
如urlpatterns的第二行所示,当首页URL附加了数字后,会将数字识别为“pageNo”,传递给views.py中的indexInPages视图函数:
def indexInPages(request, pageNo):
template = loader.get_template('blog/index.html')
allArticles = Article.objects.all().order_by('-timestamp')
p = Paginator(allArticles, 5)
articlesInPage = p.page(pageNo)
context = {
'all_articles' : articlesInPage,
}
return HttpResponse(template.render(context, request))
我们利用ORM从数据库取得所有文章数据后,创建Paginator对象(需要引用django.core.paginator模块),传入需要进行分页的数据列表(我们从数据库取得的文章数据)和每页中包含的数据条数(我们设置为5)。Django将自动为我们生成“数据切片”和与分页相关的属性信息。在这里,我们利用Paginator对象的page函数取得当前页码的数据切片,将其传入页面模板。
我们还需要对首页的页面模板进行一些修改:
{% load static %}
<htmL>
<head>
<title>欢迎光临「大狗汪叨叨」</title>
<link rel="stylesheet" type="text/css" href="{% static 'blog/css/style.css' %}">
</head>
<body>
<div style="top:20px;left:20px;position:absolute;">
![]({% static 'blog/images/logo.jpeg' %})
</div>
<div style="top:20px;left:200px;position:absolute;">
<span class="pageTitle">大狗汪叨叨</span>
</div>
<div style="left:20px;top:150px;position:absolute;width:600px;background-color:#FFFFFF;padding:20px;">
{% for article in all_articles.object_list %}
<h2 class="articleTitle">{{article.title}}</h2>
<p class="articleAuthor">by: {{article.author}} {{article.timestamp}}</p>
<span class="articleBody">{{article.body|slice:'200'}}...</span>
<br/>
<a href="article/{{article.id}}">查看全文</a>
{% endfor %}
{% if all_articles.has_previous %}
<div style="left:200px;position:absolute;width:60px;margin:30px;">
<a href="{{all_articles.previous_page_number}}"><< 前滚翻</a>
</div>
{% endif %}
{% if all_articles.has_next %}
<div style="left:340px;position:absolute;width:60px;margin:30px">
<a href="{{all_articles.next_page_number}}">后滚翻 >></a>
</div>
{% endif %}
</div>
</body>
</html>
首先,我们需要修改for循环语句,因为当前传入的是数据切片,而不是原来的数据列表了,所以我们需要将其由“all_articles”改为“all_articles.object_list”。
不过,大狗也发现views.py中的indexInPages函数,和index函数存在很多重复部分。想想看,其实第一次访问首页,也不过就是查看所有文章数据的第一页嘛,对吧?所以,我们索性把index函数改成:
def index(request):
return indexInPages(request,1)
我们把开发服务器跑起来看一下:
第一页 第二页 最后一页大狗已经将本教程中相关的代码放在GitHub上:
如果大家发现教程中有任何错误,请帮我指正;如果大家喜欢我的教程,请帮我点击文章下面的“喜欢”,您的一秒钟可以让这篇教程被更多人读到。谢谢:)