Django学习笔记5:页面参数传递与分页

页面参数的传递与获取

在上面的教程中,我们已经搭建了一个最最简(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 %}

现在,让我们把开发服务器跑起来,看看效果吧:

![显示文章简介](http://wx1.sinaimg.cn/mw690/566f9abdly1fdanp5pw6wj20go0afgn3.jpg

点击“查看全文”链接后,在单独的页面中显示全文:

《Django学习笔记5:页面参数传递与分页》 显示全文

看上去还不错(妹纸从边上经过,不屑的说“这个丑爆了好吗?没有导航栏没有回到首页链接没有页脚,弱爆了好吗?”)好吧,大狗只是验证一下页面参数传递,至于布局,我会抽出时间改的,我保证!

分页?很简单

离大狗上班还有一些时间,我们再给博客首页添加一个必要的功能:分页。

以前大狗用ASP.net做网站开发的时候,涉及到分页,总是要写很多的“八股文”式的代码:从数据库取得数据,设置每页包含记录数,计算页数,创建当前页面显示数据的列表,在页面上判断是否应该显示“上一页”和“下一页”,等等,等等。稍有疏忽,就会搞出“Index out of range”之类的东东,

而Django用Paginator类提供了标准的分页功能,大大减少了我们的编码量。

大狗的设想是,可以在首页地址后面附加一个数字,用来标识当前页码,比如“http://127.0.0.1:8000/blog/1” 表示当前查看第一页,而“http://127.0.0.1:8000/blog/2” 表示当前查看第二页,由此类推。

首先,我们需要在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”。

然后,我们文章列表的下方增加了“上一页”和“下一页”的链接,为了向大狗最喜欢的博客之一 煎蛋网 致敬,大狗将文字设置成了“前滚翻”和“后滚翻”。Django的数据切片对象中包含了“has_previous”属性,用来判断当前页是否是第一页,而“has_next”则用来判断当前页是否是最后一页。如果是第一页的话,就不应该显示“前滚翻”,同理,如果是最后一页,则不应该显示“后滚翻”。至于链接地址,则可以利用数据切片对象的“previous_page_number”和“next_page_number”属性。

大家可以看到,我们只编写了大约相当于ASP.net五分之一的代码,就在我们的博客中实现了分页功能。

不过,大狗也发现views.py中的indexInPages函数,和index函数存在很多重复部分。想想看,其实第一次访问首页,也不过就是查看所有文章数据的第一页嘛,对吧?所以,我们索性把index函数改成:

def index(request):
    return indexInPages(request,1)

我们把开发服务器跑起来看一下:

《Django学习笔记5:页面参数传递与分页》 第一页
《Django学习笔记5:页面参数传递与分页》 第二页
《Django学习笔记5:页面参数传递与分页》 最后一页

大狗已经将本教程中相关的代码放在GitHub上:

https://github.com/mingyeh/DjangoQuickTour

如果大家发现教程中有任何错误,请帮我指正;如果大家喜欢我的教程,请帮我点击文章下面的“喜欢”,您的一秒钟可以让这篇教程被更多人读到。谢谢:)

    原文作者:只喝摩卡的狗
    原文地址: https://www.jianshu.com/p/ea02c10ba278
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞