練習Django Paginator的使用使頁面更整潔。
第一階段
首先要做的是搭建整個框架,包括如何連接數據庫,如何應用model 以及Django Template Language的使用。
- 命題作文第一步當然要研究清楚命題。瀏覽器中打開代碼檢查器查看頁面結構,提取出需要準備的信息,到models.py中定義自己的模式:
class ArticleList(Document):
subject = StringField() # article subject
author = StringField() # the author
portrait = StringField() # a pic url of the author
images = ListField(StringField()) # urls of images used in the article
categories = ListField(StringField()) # tags of the article
description = StringField() # the description of the article
meta = {
'collection': 'artiinfo'
}
- 準備數據。按照第一步中取出的數據模式新建數據表'artiinfo'。
例子中第三篇文章的描述信息是兩張圖片,處理與其它文章不同,先把它放一邊,只處理純文字的文章。
authorlist = ['Tilo Mitra', 'Eric Ferra', 'Reid Burke', 'Andrew Wooldridge']
portraitlist = ['img/common/tilo-avatar.png', 'img/common/ericf-avatar.png', 'img/common/reid-avatar.png', 'img/common/andrew-avatar.png']
imageslist = [[], [],['http://farm8.staticflickr.com/7382/8907351301_bd7460cffb.jpg', 'http://farm8.staticflickr.com/7448/8915936174_8d54ec76c6.jpg'], []]
categorylist = [['CSS', 'Pure'], ['JavaScript'], [], ['YUI']]
description = ['Yesterday at CSSConf, we launched Pure – a new CSS library. Phew! Here are the slides from the presentation. Although it looks pretty minimalist, we’ve been working on Pure for several months. After many iterations, we have released Pure as a set of small, responsive, CSS modules that you can use in every web project.','Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.','','We are happy to announce the release of YUI 3.10.2! You can find it now on the Yahoo! CDN, download it directly, or pull it in via npm. We’ve also updated the YUI Library website with the latest documentation.']
titlelist = ['Introducing Pure', 'Everything You Need to Know About Grunt', 'Photos from CSSConf and JSConf', 'YUI 3.10.2 Released']
將上面準備好的數據插入數據表'blog.artiinfo'
- 準備靜態資源,css, img等
將網頁中用到的圖片資源,css文件放到static目錄下,并在settings.py中指定引用路徑。 - 定義model, 連接mongodb
settings.py中添加連接mongodb的代碼
from mongoengine import connect
connect('blog', host='127.0.0.1', port=27017)
Tip: model中的變量要與引用的數據表中的數據一一對應,名字也要完全相同,且一個不能多也一個不能少。切記!切記!
class ArticleList(Document):
subject = StringField()
author = StringField()
portrait = StringField()
images = ListField(StringField())
categories = ListField(StringField())
description = StringField()
meta = {
'collection': 'artiinfo'
}
- 在views.py中應用定義的model
# Create your views here.
def menublog(request):
info = ArticleList.objects
context = {'artiinfo': info}
return render(request, 'index.html', context)
- 編輯templates
{% load static %}
......
{% for item in artiinfo %}
<section class="post">
<header class="post-header">
<img class="post-avatar" alt="Eric Ferraiuolo's avatar" height="48" width="48" src="">
<h2 class="post-title">{{ item.subject }}</h2>
<p class="post-meta">
By <a class="post-author" href="#">{{ item.author }}</a> under
{% for ia in item.categories %}
<a class="post-category post-category-js" href="#">{{ ia }}</a>
{% endfor %}
</p>
</header>
<div class="post-description">
<p>
{{ item.description }}
</p>
</div>
</section>
{% endfor %}
......
第一階段完成。
目前為止處理了文字相關的部分。作者的頭像尚未加載。
除此之外,還有三個需要優化的問題:
標簽的顏色與標簽內容相關。
示例頁面中標簽'CSS'的背景色為綠色,查看網頁源碼發現其class="post-category post-category-design";標簽'Pure'的背景色為藍色,class="post-category post-category-pure"。'post-category-design'與'post-category-pure'這兩個class在CSS中被定義為不同的背景色。
數據表中保存的標簽信息并沒其對應的class信息,只有文字:
categorylist = [['CSS', 'Pure'], ['JavaScript'], [], ['YUI']]
那么如何做匹配呢? 如何為各個標簽指定對應的class。四篇文章中有一篇的description是兩張圖片,其它都是文字描述。需要在templates中添加代碼做相應的判斷,是圖片則顯示圖片,只有文字則顯示文字。
示例頁面中,文章分為置頂的與最近發布的兩類,為了簡化在第一階段的學習中,把所有文章都加在最近發布的類別下面。 后面會為各文章添加一個字段用于標識其類別,并實現在templates中識別此標識為文章分類顯示。
第二階段
準備更多數據,實現分頁顯示。
- views.py中添加paginator相關的代碼
from django.shortcuts import render
from myblog.models import ArticleList
from django.core.paginator import Paginator
# Create your views here.
def artilist(request):
limit = 4
arti_info = ArticleList.objects[:4]
paginator = Paginator(arti_info, limit)
page = request.GET.get('page',1)
loaded = paginator.page(page)
context = {
'artiinfo': loaded
}
return render(request, 'index.html', context)
- templates模板中添加翻頁按鈕
<div class="paginator">
{% if artiinfo.has_previous %}
<a href="?page={{ artiinfo.previous_page_number }}">Previous</a>
{% endif %}
<span>{{ artiinfo.number }} of {{ artiinfo.paginator.num_pages }}</span>
{% if artiinfo.has_next %}
<a href="?page={{ artiinfo.next_page_number }}">Next</a>
{% endif %}
</div>
分頁顯示效果圖
進階學習
變量item.portrait中保存的是各文章作者的頭像路徑,且都是相對路徑,相對于static。如'img/common/tilo-avatar.jpg'。
當路徑是一個變量,且關聯static目錄時,引用方法如下
(https://docs.djangoproject.com/en/1.9/ref/templates/builtins/):
src="{% static item.portrait %}
- 優化問題一
templates模板中加入了條件判斷語句,實現標簽與class的對應,從而各個標簽顯示各自特定的背景色。
<p class="post-meta">
By <a class="post-author" href="#">{{ item.author }}</a> under
{% for tag in item.categories %}
{% if tag == 'JavaScript' %}
<a class="post-category post-category-js" href="#">{{ tag }}</a>
{% elif tag == 'CSS' %}
<a class="post-category post-category-design" href="#">{{ tag }}</a>
{% elif tag == 'Pure' %}
<a class="post-category post-category-pure" href="#">{{ tag }}</a>
{% elif tag == 'YUI' %}
<a class="post-category post-category-yui" href="#">{{ tag }}</a>
{% else %}
<a class="post-category" href="#">{{ tag }}</a>
{% endif %}
{% endfor %}
</p>
- 優化問題二
對<div class="post-description">的修改如下:
...
<div class="post-description">
{% if item.images %}
<div class="post-images pure-g">
{% for img in item.images %}
<div class="pure-u-1 pure-u-md-1-2">
<a href="">

</a>
<div class="post-image-meta">
<h3></h3>
</div>
</div>
{% endfor %}
</div>
{% endif %}
<p>
{{ item.description }}
</p>
</div>
...
效果圖
- 優化問題三
為每篇文章添加一個屬性用來標識其是否為置頂。
在templates中添加代碼判斷一篇文章是否是'pinned', 如果是則在'Pinned Post' wrapper中為其生成一個section。
在'Recent Posts'中做類似的判斷,當一篇文章不是'pinned', 則為其創建section。
<!-- A wrapper for all the blog posts -->
<div class="posts">
<h1 class="content-subhead">Pinned Post</h1>
<!-- A single blog post -->
{% for item in artiinfo %}
{% if item.level == 'pinned' %}
<section class="post">
......
</section>
{% endif %}
{% endfor %}
</div>
<div class="posts">
<h1 class="content-subhead">Recent Posts</h1>
{% for item in artiinfo %}
{% if item.level != 'pinned' %}
<section class="post">
......
</section>
{% endif %}
{% endfor %}
</div>
思考: 這樣處理帶來一個問題。作為讀者希望標注了'pinned'的文章始終置頂。但用上面的方法,如果'pinned'文章在數據庫中id為5, 也就是第五篇文章,paginator以4篇文章為一頁,這篇'pinned'文章就被劃分在第二頁。最終顯示的效果將是瀏覽第一頁時,'pinned post'類別下沒有文章,瀏覽第二頁時,'pinned post'下顯示出了這篇'pinned'文章。
這個效果顯示不夠好。
理想的處理方式考慮下來是將'pinned'單獨篩選出來。僅對那些沒有'pinned'標注的文章應用paginator分頁顯示。