Flask 系列之 Pagination

说明

  • 操作系统:Windows 10
  • Python 版本:3.7x
  • 虚拟环境管理器:virtualenv
  • 代码编辑器:VS Code

实验目标

实现当前登录用户的事务浏览、添加、删除 操作

实现

首先,在我们的 todolist\forms.py 中添加事务添加对应的表单类 ThingForm,示例代码如下所示:

from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField, TextAreaField, PasswordField
from wtforms.validators import DataRequired, Length, Email, EqualTo, ValidationError
from models import User

class RegisterForm(FlaskForm):
    username = StringField('用户名:', validators=[
                           DataRequired(), Length(min=6, max=20)])
    email = StringField('邮箱:', validators=[DataRequired(), Email()])
    pwd = PasswordField('密码:', validators=[
        DataRequired(), Length(min=8, max=120)])
    confirm = PasswordField('确认密码:', validators=[
                            DataRequired(), EqualTo('pwd')])
    submit = SubmitField('提交')

    def validate_username(self, username):
        user = User.query.filter_by(name=username.data).first()
        if user:
            raise ValidationError("用户昵称已存在。")

    def validate_email(self, email):
        user = User.query.filter_by(email=email.data).first()
        if user:
            raise ValidationError('邮箱已存在.')

class LoginForm(FlaskForm):
    username = StringField('用户名:', validators=[
                           DataRequired(), Length(min=6, max=20)])
    password = PasswordField('密码:', validators=[DataRequired()])
    submit = SubmitField('登陆')

    def validate_username(self, username):
        user = User.query.filter_by(name=username.data)
        if not user:
            raise ValidationError('用户名不存在。')

class ThingForm(FlaskForm):
    title = StringField('标题:', validators=[
                        DataRequired(), Length(min=6, max=20)])
    text = TextAreaField('内容:', validators=[DataRequired()])
    submit = SubmitField('提交')

接着修改 todolist\app\views.py ,添加当前用户事务的添加、删除,示例代码如下所示:

from flask import render_template, redirect, url_for, flash, request
from flask_login import login_user, login_required, current_user, logout_user
from app import app, db
from forms import ThingForm, RegisterForm, LoginForm
from models import User, Thing

@app.context_processor
def inject_user():
    user = User.query.first()
    return dict(user=user)

@app.route('/', methods=['GET', 'POST'])
@app.route('/index', methods=['GET', 'POST'])
def index():
    form = ThingForm()
    if not current_user.is_authenticated:
        return redirect(url_for('login'))
    if request.method == 'POST' and form.validate_on_submit():
        user_id = current_user.id
        title = form.title.data
        text = form.text.data
        thing = Thing(user_id=user_id, title=title, text=text)
        db.session.add(thing)
        db.session.commit()
        flash('添加成功')
    page = request.args.get('page', 1, type=int)
    things = current_user.things.order_by(
        Thing.add_date.desc()).paginate(page, 2, False)
    print(things)
    return render_template('index.html', title="首页", form=form, things=things)

@app.route('/login', methods=['POST', 'GET'])
def login():
    form = LoginForm()
    if form.validate_on_submit():
        name = form.username.data
        pwd = form.password.data
        user = User.query.filter_by(name=name).first()
        if user and user.check_password_hash(pwd):
            login_user(user)
            flash('登陆成功。', category='info')
            return redirect(url_for('index'))
        else:
            flash("密码或账户错误。", category='error')
    return render_template('login.html', title='登录', form=form)

@app.route('/logout')
@login_required
def logout():
    logout_user()
    flash('再见!')
    return redirect(url_for('login'))

@app.route('/register', methods=['POST', 'GET'])
def register():
    form = RegisterForm()
    if form.validate_on_submit():
        username = form.username.data
        email = form.email.data
        pwd = form.pwd.data
        user = User(name=username, email=email)
        user.generate_password_hash(pwd)
        db.session.add(user)
        db.session.commit()
        flash('注册成功', category='info')
        return redirect(url_for('login'))
    return render_template('register.html', title='注册', form=form)

@app.route('/delete/<int:id>')
@login_required
def delete(id):
    thing = Thing.query.get(id)
    if thing:
        db.session.delete(thing)
        db.session.commit()
        return redirect(url_for('index'))

最后,完善 todolist\app\templates\index.html,添加数据展示相关代码,示例代码如下所示:

{% extends 'base.html' %} {% block content %} {% if current_user.is_authenticated and user %}
<h1 class="m-4">{{ current_user.name }},欢迎回来</h1>
{% endif %}

<div class="container-fluid">
    <p>
        <a class="btn btn-primary" data-toggle="collapse" href="#collapseExample" role="button" aria-expanded="false" aria-controls="collapseExample">
            添加新事务
        </a>
    </p>
    <div class="collapse" id="collapseExample">
        <div class="card card-body mb-4">
            {% from 'bootstrap/form.html' import render_form %} {{ render_form(form) }}
        </div>
    </div>

    <ul class="list-group">
        {% for thing in things.items %}
        <li class="list-group-item">
            <h4 style="display:block;float:left;padding-top:2px">
                {{ thing.title }}
            </h4>
            <div style="display:block;float: right;">
                <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModalCenter{{thing.id}}">查看</button>
                <a class="btn btn-danger" href='/delete/{{ thing.id }}'>删除</a>
            </div>
        </li>

        <div class="modal fade" id="exampleModalCenter{{thing.id}}" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
            <div class="modal-dialog modal-dialog-centered" role="document">
                <div class="modal-content">
                    <div class="modal-header">
                        <h5 class="modal-title" id="exampleModalLongTitle">{{ thing.title }}</h5>
                    </div>
                    <div class="modal-body">
                        {{ thing.text }}
                    </div>
                    <div class="modal-footer">
                        <small>{{ thing.add_date }}</small>
                        <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
                    </div>
                </div>
            </div>
        </div>
        {% endfor %}
    </ul>

    <nav aria-label="Page navigation example" class="m-4">
        <ul class="pagination justify-content-center">
            <li class="page-item {% if not things.has_prev %}disabled{% endif %}">
                <a class="page-link" href="{{ url_for('index',page=things.prev_num) }}">上一页</a>
            </li>

            {% for page in things.iter_pages(1,1,3,2) %} {% if page %}
            <li class="page-item {%if page==things.page%}active{%endif%}">
                <a class="page-link" href="{{ url_for('index',page=page) }}">{{page}}</a>
            </li>
            {% else %}
            <li class="page-item disabled">
                <a class="page-link" href="#">&hellip;</a>
            </li>
            {% endif %} {% endfor %}

            <li class="page-item {% if not things.has_next %}disabled{% endif %}">
                <a class="page-link" href="{{ url_for('index',page=things.next_num) }}">下一页</a>
            </li>
        </ul>
    </nav>

</div>

{% endblock %}

此时,当我们运行起我们的网站后进入注册页面 http://127.0.0.1:5000 就可以进行当前登录用户的事务录入、查看、删除、和事务分页的效果了。

补充

一个 Pagination 对象的常用属性有:

  • items 当前页面中的所有记录(比如当前页上有5条记录,items就是以列表形式组织这5个记录)
  • query 当前页的query对象(通过query对象调用paginate方法获得的Pagination对象)
  • page 当前页码(比如当前页是第5页,返回5)
  • prev_num 上一页页码
  • next_num 下一页页码
  • has_next 是否有下一页 True/False
  • has_prev 是否有上一页 True/False
  • pages 查询得到的总页数 per_page 每页显示的记录条数
  • total 总的记录条数

常用方法有:

  • prev() 上一页的分页对象Pagination
  • next() 下一页的分页对象Pagination
  • iter_pages(left_edge=2,left_current=2,right_current=5,right_edge=2)
  • iter_pages 用来获得针对当前页的应显示的分页页码列表。
  • 假设当前共有100页,当前页为50页,按照默认的参数设置调用iter_pages获得的列表为:[1,2,None,48,49,50,51,52,53,54,55,None,99,100]

原文地址:https://www.cnblogs.com/hippieZhou/p/10605831.html

时间: 2024-11-13 11:17:19

Flask 系列之 Pagination的相关文章

Flask系列:数据库

这个系列是学习<Flask Web开发:基于Python的Web应用开发实战>的部分笔记 对于用户提交的信息,包括 账号.文章 等,需要能够将这些数据保存下来 持久存储的三种方法: 文件:shelve(pickle 和 DBM 的结合)等,提供类似字典的对象接口 关系型数据库(SQL) 非关系型数据库(NoSQL) 其他 通常会使用数据库保存信息,并向数据库发起查询获取信息 SQL,关系型数据库 关系型数据库把数据存储在表中,表在程序中通过 Python 的类实现.例如,订单管理程序的数据库中

flask系列一之环境搭建包安装

一,python的安装 (1)python的安装 (2)虚拟环境的配置 参考:http://www.cnblogs.com/bfwbfw/p/7995245.html 1,虚拟环境的建立 (1)使用pip安装虚拟环境 pip install virtualenv (2)安装包管理虚拟环境 pip install virtualenvwrapper-win (3)使用mkvirtualenv 命令安装项目虚拟环境 mkvirtualenv ZhiLiaoProject 2,通过pycharm新建一

Flask系列(十)自定义Form组件

一.wtforms源码流程 1.实例化流程分析 # 源码流程 1. 执行type的 __call__ 方法,读取字段到静态字段 cls._unbound_fields 中: meta类读取到cls._wtforms_meta中 2. 执行构造方法 a. 循环cls._unbound_fields中的字段,并执行字段的bind方法,然后将返回值添加到 self._fields[name] 中. 即: _fields = { name: wtforms.fields.core.StringField

Flask系列(九)flask-script组件

Flask Script扩展提供向Flask插入外部脚本的功能,包括运行一个开发用的服务器,一个定制的Python shell,设置数据库的脚本,cronjobs,及其他运行在web应用之外的命令行任务:使得脚本和系统分开: Flask Script和Flask本身的工作方式类似,只需定义和添加从命令行中被Manager实例调用的命令: 官方文档:http://flask-script.readthedocs.io/en/latest/ 一.创建并运行命令 首先,创建一个Python模板运行命令

Flask 系列之 FlaskForm

通过使用 FlaskForm ,可以方便快捷的实现表单处理. 说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 通过使用 flask_wtf 进行表单的相关操作,并完成新用户合法性注册. 安装 pip install flask_wtf 使用 首先,我们在 todolist 目录中创建一个 forms.py 文件,定义一个注册的表单类, 用于完成用户注册.示例代码如下所示: from flask_wtf

Flask系列 路由系统

Flask路由系统细分 from flask import Flask app = Flask(__name__) @app.route('/') def index(): return 'ok' if __name__ == '__main__': app.run() 从这个简单的代码入口,来剖析一下路由@app.route('/') route():就是一个加在index()上的装饰器 ?```python def route(self, rule, **options): # rule:匹

Flask源码分析一:服务启动

前言 Flask是目前为止我最喜欢的一个Python Web框架了,为了更好的掌握其内部实现机制,这两天准备学习下Flask的源码,将由浅入深跟大家分享下,其中Flask版本为1.1.1. Flask系列文章: Flask开发初探 正文 本文将结合源码跟踪看下Flask是如何启动并运行一个服务的. 首先,继续贴上最简单的应用: from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): retu

Flask容器化部署原理与实现

本文将介绍Flask的部署方案:Flask + Nginx + uWSGI,并使用docker进行容器化部署,部署的实例来源 Flask开发初探,操作系统为ubuntu. Flask系列文章: Flask开发初探 WSGI到底是什么 Flask源码分析一:服务启动 Flask路由内部实现原理 部署方案 在开发时,我们使用flask run命令启动的开发服务器是werkzeug提供的,但是这种方式目的是为了开发,不能很好的扩展,不适合生产部署.生产部署,我们需要一个更强健,性能更高的WSGI服务器

Flask权限管理

权限管理是一个很常见的功能模块,本文基于RBAC模型针对于多用户,多角色,多权限的场景,介绍一种Flask权限管理方案. Flask系列文章: Flask开发初探 WSGI到底是什么 Flask源码分析一:服务启动 Flask路由内部实现原理 Flask容器化部署原理与实现 本文将在开发初探的代码基础上进行重构. 介绍 在本文所述场景中,具体的权限管理是:权限和角色关联,给用户添加角色,用户即拥有角色的权限,也就是基于角色的权限控制.当然,若需要基于用户的权限控制也是可以的,只需要修改下相关数据