flask_分頁


一、提交博客文章

1.定義一個單字段的表單對象(form.py)

1 class PostForm(Form):
2     post = StringField('post', validators=[DataRequired()])

2.把表單添加到模板中:(templates/user.html)

 1 {% extends "base.html" %}
 2 {% block content %}
 3 <h1>Hi, {{user.nickname}}!</h1>
 4 <form action="" method="post" name="post">
 5     {{form.hidden_tag()}}
 6     <table>
 7         <tr>
 8             <td>Say something:</td>
 9             <td>{{ form.post(size = 30, maxlength = 140) }}</td>
10             <td>
11             {% for error in form.errors.post %}
12                 <span style="color: red;">[{{error}}]</span><br>
13             {% endfor %}
14             </td>
15         </tr>
16         <tr>
17             <td></td>
18                 <td><input type="submit" value="Post!"></td>
19             <td></td>
20         </tr>
21     </table>
22 </form>
23 {% for post in posts %}
24     {% include 'post.html' %}
25 {% endfor %}

3.利用視圖函數來處理表單

 1 from form import LoginForm,EditForm,PostForm
 2 @app.route('/')
 3 @login_required
 4 def index():
 5     user=g.user
 6     form=PostForm()
 7     from model import Post
 8     from model import db
 9     if form.validate_on_submit():
10         post=Post(body=form.post.data,timestamp=datetime.utcnow(),user_id=user.id)
11         db.session.add(post)
12         db.session.commit()
13         flash('Your post is now live!')
14         return redirect(url_for('index'))
15     posts=user.followed_posts()
16     print "posts:",posts
17     return render_template('index.html',title='home',form=form,user=user,posts=posts)

注:這里我們解釋一下為什么要重定向到首頁(index)

如果一個用戶正在撰寫 blog,接着不小心按到了瀏覽器的刷新鍵,會發生些什么。刷新的命令將會做些什么?瀏覽器將會重新發送上一次的請求作為刷新命令的結果。沒有重定向,上一次的請求是提交表單的 POST 請求,因此刷新動作將會重新提交表單,導致與第一個相同的第二個 Post 記錄被寫入數據庫。這並不好。有了重定向,我們迫使瀏覽器在表單提交后發送另外一個請求,即重定向頁的請求。這是一個簡單的 GET 請求,因此一個刷新動作將會重復 GET 請求而不是多次提交表單。

二、分頁

Flask-SQLAlchemy 天生就支持分頁。比如說我們想要在第一頁顯示前三條blog,我們可以這么做:

posts=user.followed_posts().paginate(1, 3, False).items

paginate 方法能夠被任何查詢調用。它接受三個參數:

1.頁數,從1開始

2.每一頁顯示的blog數目

3.錯誤標志。如果是 True,當請求的范圍頁超出范圍的話,一個 404 錯誤將會自動地返回到客戶端的網頁瀏覽器。如果是 False,返回一個空列表而不是錯誤。

從 paginate 返回的值是一個 Pagination 對象。這個對象的 items 成員包含了請求頁面項目(本文是指 blog)的列表。在 Pagination 對象中還有其它有幫助的東西,我們將在后面能看到。

現在讓我們想想如何在我們的 index 視圖函數中實現分頁。我們首先在配置文件中添加一些決定每頁顯示的 blog 數的配置項(文件 config.py):

# 每頁顯示的blog數
POSTS_PER_PAGE = 3

接着,讓我們看看不同頁的 URLs 是什么樣的。我們知道 Flask 路由可以攜帶參數,因此我們在 URL 后添加一個后綴表示所需的頁面:

http://localhost:5000/         <-- page #1 (default)
http://localhost:5000/index    <-- page #1 (default)
http://localhost:5000/index/1  <-- page #1
http://localhost:5000/index/2  <-- page #2

這種格式的 URLs 能夠輕易地通過在我們的視圖函數中附加一個 route 來實現(文件microblog.py):

 1 @app.route('/index<int:page>',methods=['GET','POST'])
 2 @login_required
 3 def index(page=1):
 4     user=g.user
 5     form=PostForm()
 6     from model import Post
 7     from model import db
 8     if form.validate_on_submit():
 9         post=Post(body=form.post.data,timestamp=datetime.utcnow(),user_id=user.id)
10         db.session.add(post)
11         db.session.commit()
12         flash('Your post is now live!')
13         return redirect(url_for('index'))
14     posts=user.followed_posts().paginate(page,POSTS_PER_PAGE,False).items
15     # print "posts:",posts
16     return render_template('index.html',title='home',form=form,user=user,posts=posts)

我們新的路由需要頁面數作為參數,並且聲明為一個整型。同樣我們也需要在 index 函數中添加 page 參數,並且我們需要給它一個默認值。

現在我們已經有可用的頁面數,我們能夠很容易地把它與配置中的 POSTS_PER_PAGE 一起傳入 followed_posts 查詢。

現在試試輸入不同的 URLs,看看分頁的效果。但是,需要確保可用的 blog 數要超過三個,這樣你就能夠看到不止一頁了!

4.在頁面中添加導航(index.html)

在我們目前的版本中我們按如下方式使用 paginate 方法:

posts=user.followed_posts().paginate(page,POSTS_PER_PAGE,False).items

通過上面這樣做,我們可以獲得返回自 paginate 的 Pagination 對象的 items 成員。但是這個對象還有很多其它有用的東西在里面,因此我們還是使用整個對象(文件microblog.py):

posts=user.followed_posts().paginate(page,POSTS_PER_PAGE,False)

修改模板index.html

這個改變使得模版能夠使用完全的 Paginate 對象。我們使用的這個對象的成員有:

(1)has_next:如果在目前頁后至少還有一頁的話,返回 True

(2)has_prev:如果在目前頁之前至少還有一頁的話,返回 True

(3)next_num:下一頁的頁面數

(4)prev_num:前一頁的頁面數

有了這些元素后,我們產生了這些(文件 app/templates/index.html):

1 {% for post in posts.items %}
2     {% include 'post.html' %}
3 {% endfor %}
4 {% if posts.has_prev %}<a href="{{ url_for('index', page = posts.prev_num) }}"><< Newer posts</a>{% else %}<< Newer posts{% endif %} |
5 {% if posts.has_next %}<a href="{{ url_for('index', page = posts.next_num) }}">Older posts >></a>{% else %}Older posts >>{% endif %}
6 {% endblock %}

因此,我們有了兩個鏈接。第一個就是名為 “Newer posts”,這個鏈接使得我們能夠訪問上一頁。第二個就是 “Older posts”,它指向下一頁。

三、修改用戶信息頁

(1)microblog.py

 1 @app.route('/user/<nickname>')
 2 @app.route('/user/<nickname>/<int:page>')
 3 @login_required
 4 def user(nickname,page=1):
 5     user =model.User.query.filter_by(nickname = nickname).first()
 6     posts=user.posts.paginate(page,POSTS_PER_PAGE,False)
 7     if user == None:
 8         flash('User ' + nickname + ' not found.')
 9         return redirect(url_for('index'))
10     return render_template('user.html',
11         user = user,
12         posts = posts)

(2)user.html

1 {% for post in posts.items %}
2     {% include 'post.html' %}
3 {% endfor %}
4 {% if posts.has_prev %}<a href="{{ url_for('user', nickname = user.nickname, page = posts.prev_num) }}"><< Newer posts</a>{% else %}<< Newer posts{% endif %} |
5 {% if posts.has_next %}<a href="{{ url_for('user', nickname = user.nickname, page = posts.next_num) }}">Older posts >></a>{% else %}Older posts >>{% endif %}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM