zoukankan      html  css  js  c++  java
  • 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 %}
  • 相关阅读:
    跨浏览器OCX
    安装QT5.02
    Ubuntu登陆密码忘记
    QTableView
    VMware安装时Error 1324. The path My Documents contains a invalid character的原因和解决方法
    VS2005 与虚拟机的那点事
    创建掩码位图来实现透明绘图
    【转载】spring注解整理
    记录spring test类无法插入数据问题
    Uniapp 原生开发uniapp.arr 新老兼容问题
  • 原文地址:https://www.cnblogs.com/ninicwang/p/6027159.html
Copyright © 2011-2022 走看看