python对列表进行分页_python列表分页
上章的結(jié)束,若在實(shí)際開發(fā)過程中,會(huì)發(fā)現(xiàn)一個(gè)問題,那就首頁或關(guān)注分享,是一下子按時(shí)間順序全部顯示出來,這在實(shí)際項(xiàng)目中不可能出現(xiàn)的,想想實(shí)際中的產(chǎn)品是如何做的?
一般來說,無非是兩種,一種是使用頁碼,來進(jìn)行分頁,還有一種是js到頁底自動(dòng)加載,而使用頁底自動(dòng)加載的話,上一章實(shí)現(xiàn)的通過tab來區(qū)分全部和關(guān)注就不可取了,因?yàn)闊o法保證兩個(gè)tab加載的內(nèi)容數(shù)量一致,導(dǎo)致頁面布局就無法實(shí)現(xiàn),所以,這里首頁參考tumblr的實(shí)現(xiàn)方式,刪除關(guān)注分享的部分,只保留全部分享,使用js頁底動(dòng)態(tài)加載分頁方式,同時(shí)在導(dǎo)航欄新增兩個(gè)導(dǎo)航,分別為博文,和關(guān)注,使用傳統(tǒng)頁碼的方式顯示全部博文和已關(guān)注博文,這樣是為了有些人可能會(huì)查詢比較久的歷史信息,所以,一個(gè)頁面,一個(gè)功能如何設(shè)計(jì),主要取決于業(yè)務(wù)需求,而不是技術(shù)需求。首先修改導(dǎo)航(base.html):
{% if current_user.is_authenticated %}
aria-haspopup="true" aria-expanded="false">關(guān)注
{% endif %}
用戶登錄后,在首頁后面會(huì)新增兩個(gè)item,分別是分享和關(guān)注,其中關(guān)注是一個(gè)下拉菜單,分別是“我”關(guān)注的用戶發(fā)布的分享,和“我”關(guān)注的用戶
下面完成這幾個(gè)頁面,首先是分享頁,即所有用戶發(fā)布的分享,頁面與之前的首頁很像,首先完成視圖模型:
@main.route("/post")
@main.route("/post/")
def post(page=1):
pagination=Post.query.order_by(Post.createtime.desc()).paginate(
page,per_page=current_app.config["POSTS_PER_PAGE"],error_out=False
)
return render_template("posts.html",posts=pagination.items,pagination=pagination,endpoint=request.endpoint)
這個(gè)模型的route的意思是,既可以通過/post訪問,也可以通過/post/1等類型訪問,當(dāng)/post訪問的時(shí)候,默認(rèn)訪問第一頁。
endpoint的意思為訪問的端點(diǎn),即方法的端點(diǎn),針對(duì)于這個(gè)方法來說,endpoint的值為"main.post"
接下來的內(nèi)容,就是本章的一個(gè)重點(diǎn)了,pagination對(duì)象,這個(gè)是flask-SQLAlchemy框架中的一個(gè)很重要的對(duì)象,它包含了一系列用于分頁的屬性,其中主要的屬性如下:
has_next
是否還有下一頁
has_prev
是否還有前一頁
items
當(dāng)前頁的數(shù)據(jù)
iter_pages(left_edge=2,left_current=2,right_current=5,right_edge=2)
一個(gè)關(guān)于頁面的迭代,可以有四個(gè)帶有默認(rèn)值的參數(shù):
left_edge 頁碼最左邊顯示的頁數(shù)
left_current 當(dāng)前頁左邊顯示的頁數(shù)
right_current 當(dāng)前頁右邊顯示的頁數(shù)
right_edge 頁面最右邊顯示的頁數(shù)
可能有些不好理解,舉個(gè)例子,假設(shè)共100頁,當(dāng)前為50頁,則顯示如下:
1,2...48,49,50,51,52,53,54,55...99,100
next(error_out=False)
下一頁的分頁對(duì)象,當(dāng)error_out為true時(shí),超過頁面返回404
prev(error_out=False)
上一頁的分頁對(duì)象
page
當(dāng)前頁碼
prev_num
上頁頁碼
next_num
下頁頁碼
per_page
每頁顯示的記錄數(shù)量
total
記錄總數(shù)
還有更多屬性,請(qǐng)查驗(yàn)文檔
分享頁的模板與首頁幾乎一樣,同樣是一個(gè)分享發(fā)布框,一個(gè)已分享列表(posts.html):
{% import "_index_post_macros.html" as macros %}...
{% if current_user.is_authenticated %}{{ wtf.quick_form(form) }}{% endif %}
{{macros.rander_posts(posts,moment,pagination,endpoint)}}
{% if current_user.is_authenticated %}
我已經(jīng)分享{{ current_user.posts.count() }}條心情
我已經(jīng)關(guān)注了{{ current_user.followed.count() }}名好友
我已經(jīng)被{{ current_user.followers.count() }}名好友關(guān)注
{%endif%}
{% endblock %}{% block scripts %}{{ super() }}{{ pagedown.include_pagedown() }}
e.preventDefault()
$(this).tab('show')
})
{% endblock%}
并沒有做過多的封裝,其實(shí)完全可以把右側(cè)在封裝成為一個(gè)macro
接下來是_index_post_macros.html
{% macro rander_posts(posts,moment,pagination=None,endpoint=None) %}{% import "_posts_page_macros.html" as macros %}{% for post in posts %}
{% if post.body_html%}{{post.body_html|safe}}{% else %}{{post.body}}{% endif %}
{{post.author.nickname}}
發(fā)表于?{{ moment( post.createtime).fromNow(refresh=True)}}
{% endfor %}{% if pagination and endpoint %}{{macros.rander_page(pagination,endpoint)}}{% endif %}{%endmacro%}
這里需要注意的一點(diǎn)也就是最下邊新增的代碼,意味著macro也可以嵌套,如果pagination和endpoint不為None,則顯示頁碼,而_posts_page_macros.html的代碼如下:
{% macro rander_page(pagination,endpoint) %}
{% if pagination.has_prev %}
?
{% else %}
?
{% endif %}{% for p in pagination.iter_pages() %}{% if p%}{% if p ==pagination.page%}
{{p}}{% else %}
{{p}}{% endif %}{% else %}
...{% endif %}{% endfor %}{% if pagination.has_next %}
?
{% else %}
?
{% endif %}
{% endmacro %}
這是一個(gè)比較典型的pagination的使用方式,完全使用了bootstrap的樣式,最終的顯示效果如下:
貌似內(nèi)容有點(diǎn)少,分頁我發(fā)測(cè)試,并且之后關(guān)注分頁,首頁動(dòng)態(tài)分頁都要用,所以首先要擴(kuò)充一些分享內(nèi)容,擴(kuò)充的方式多種多樣,比如實(shí)際數(shù)據(jù),手動(dòng)修改數(shù)據(jù)庫,但對(duì)于python來說,它提供了一個(gè)不錯(cuò)的生成虛擬數(shù)據(jù)的輪子,即ForgeryPy,首先當(dāng)然還是安裝:
pip3.6 install ForgeryPy
然后修改Post類,添加一個(gè)靜態(tài)方法(Post.py)
@staticmethod
def generate_fake():
from random import seed, randint;
from .User import User
import forgery_py;
seed()
user_count = User.query.count()
for i in range(100):
u = User.query.offset(randint(0, user_count - 1)).first()
p = Post(body=forgery_py.lorem_ipsum.sentences(randint(1, 3)),
createtime=forgery_py.date.date(True), author=u)
db.session.add(p)
db.session.commit()
幾個(gè)參數(shù)說明一下:
lorem_ipsum比較有趣,原意為一些排版時(shí)的占位用的無意義字符,具體解釋可參考阮博的博客,sentences方法為生成普通句子,參數(shù)代表句子的數(shù)量。
date的參數(shù)表示生成時(shí)間的區(qū)間,True表示生成的區(qū)間都為過去的時(shí)間
這個(gè)靜態(tài)方法的使用方式為:
python manage.py shell
Post.generate_fake()
這樣就會(huì)生成100條分享。
下面在看一下分享頁的效果(尾頁):
不考慮美工的話,效果還是可以的,不過內(nèi)容都是英文的,不知道能不能有一個(gè)中文的虛擬數(shù)據(jù)生成器:)
下面是關(guān)注分享頁,和這個(gè)頁類似,視圖模型為:
@main.route("/follow_post",methods=["GET","POST"])
@main.route("/follow_post/",methods=["GET","POST"])
@login_required
def follow_post(page=1):
form = PostForm()
if form_util(form):
return redirect(url_for(request.endpoint)) # 跳回首頁
print(form.body.data)
pagination=Post.query.select_from(Follow).filter_by(follower_id=current_user.id)\
.join(Post,Follow.followed_id == Post.author_id).paginate(
page,per_page=current_app.config["POSTS_PER_PAGE"],error_out=False
)
return render_template("posts.html",posts=pagination.items,form=form,
pagination=pagination,endpoint=request.endpoint)
注意,由于關(guān)注分享,分享和首頁都有PostForm,所以把這個(gè)功能獨(dú)立出來:
def form_util(form):
if form.validate_on_submit():
post = Post(body=form.body.data, author_id=current_user.id)
db.session.add(post);
return True
return False
其實(shí)我想flask應(yīng)該有整個(gè)頁面的某一個(gè)功能獨(dú)立為一個(gè)視圖模型的方式,但我沒有找到,如果讀者找到了別忘了留言回復(fù)
最后,關(guān)注的用戶就太簡(jiǎn)單了,可以直接使用某用戶關(guān)注的頁面,將userid參數(shù)賦予當(dāng)前用戶的參數(shù)即可,最終base.html的導(dǎo)航部分代碼為:
{% if current_user.is_authenticated %}
aria-haspopup="true" aria-expanded="false">關(guān)注
{% endif %}
{% if current_user.is_authenticated %}
登出{% else %}
登錄注冊(cè){% endif %}
搜索
然后刪除首頁中tab的部分,最終代碼為:
{% if current_user.is_authenticated %}{{ wtf.quick_form(form) }}{% endif %}
{{macros.rander_posts(posts,moment)}}
{% if current_user.is_authenticated %}
我已經(jīng)分享{{ current_user.posts.count() }}條心情
我已經(jīng)關(guān)注了{{ current_user.followed.count() }}名好友
我已經(jīng)被{{ current_user.followers.count() }}名好友關(guān)注
{%endif%}
這時(shí)候,你可能已經(jīng)發(fā)現(xiàn)了,首頁的分享還沒有進(jìn)行分頁,在本章的開始部分就已經(jīng)解釋道,首頁使用動(dòng)態(tài)加載的分頁方式,而動(dòng)態(tài)加載顯然需要js的配合,使用json的方式向html中注入。這時(shí)候服務(wù)端就會(huì)面臨一個(gè)問題,如何與客戶端的js進(jìn)行交互呢,這是下一章將要說明的問題。
總結(jié)
以上是生活随笔為你收集整理的python对列表进行分页_python列表分页的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 揭秘inter平台内存超频:3步操作助你
- 下一篇: websocket python爬虫_p