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="#">…</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]
Flask 系列之 Pagination的更多相关文章
- Flask 系列之 部署发布
说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 通过 Windows 的 WSL,将我们的项目网站部署到 ...
- 【Python】Flask系列-URL和视图笔记
1.学习目标 熟悉Flask相关知识. 熟悉web开发流程. 能独立开发Flask项目. 2.环境配置 Python虚拟环境安装 因为python的框架更新迭代太快了,有时候需要在电脑上存在一个框架的 ...
- Flask 系列之 SQLAlchemy
SQLAlchemy 是一种 ORM 框架,通过使用它,可以大大简化我们对数据库的操作,不用再写各种复杂的 sql语句 了. 说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环 ...
- Flask系列(五)Flask实现分页
一.flask分页组件 from urllib.parse import urlencode,quote,unquote class Pagination(object): ""& ...
- Flask系列:数据库
这个系列是学习<Flask Web开发:基于Python的Web应用开发实战>的部分笔记 对于用户提交的信息,包括 账号.文章 等,需要能够将这些数据保存下来 持久存储的三种方法: 文件: ...
- Flask 系列之 Migration
说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 通过使用 flask-migrate 实现数据库的迁移操 ...
- Flask 系列之 Blueprint
说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 学习如何使用 Blueprint 介绍 接触过 DotN ...
- Flask 系列之 优化项目结构
说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 完善环境配置,添加 异常请求 处理 实现 400.404 ...
- Flask 系列之 LoginManager
说明 操作系统:Windows 10 Python 版本:3.7x 虚拟环境管理器:virtualenv 代码编辑器:VS Code 实验目标 通过使用 flask-login 进行会话管理的相关操作 ...
随机推荐
- Appium + Python 测试 QQ 音乐 APP的一段简单脚本
1. 大致流程 + 程序(Python):打开 QQ 音乐,点击一系列接收按键,进入搜索音乐界面,输入『Paradise』,播放第一首音乐. 2. Python 脚本如下 from appium im ...
- Javascript高级编程学习笔记(54)—— DOM2和DOM3(6)范围选择
范围 为了让开发人员更加方便地控制页面“DOM2级遍历和范围”模块定义了“范围”接口 通过该接口开发人员可以选择文档中的一个区域,而不必考虑元素的界限 在常规操作不能有效地修改文档时,使用范围往往可以 ...
- es5
var arr1=["上海","北京","广州"]; var arr2=[12,22, 33,58,32,45,92]; // 数组.方法( ...
- JDK设计模式之—单例模式和static关键字
首先了解static 关键字 static声明的方法是静态方法,static声明的成员变量为静态成员变量.对于该类的所有对象来说,static的成员变量和static只有一份存储空间 即使没有创建该类 ...
- 签名时出错: 未在路径 C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin
在运行winform程序时,由于清理解决方案等缘故,出现了下面的情况 解决办法:项目-属性-签名-取消勾选“为ClickOne清单签名” 问题完美解决
- 【sping揭秘】25、Spring远程方案
分化:RMI,EJB,Hessian Spring有 Rmi,http,hessian,burlap 基于rmi的remoting方案 RMI要求远程类对象包路径和本地一致 基于HTTP的轻量级rem ...
- .NET图平台下的图像处理工具---强大的Emgucv
图像一直与时代相伴,图形化的应用软件也重不可缺.对于MFC.Delphi.Lazarus.Qt大家可能已经耳熟能详.对于很多图像处理的开源库,很多都是用C\C++写的,而.Net下的开源库以前很少了解 ...
- ionic3 npm install cordova error syscall rename
突然出现cordova 不是内部或外部命令,也不是可运行的程序或批处理文件. 可是之前cordova安装后一直用的好好的啊,后来尝试重新安装cordova 出现这个错误.也尝试重新安装了最新版本的no ...
- 从Java小白到收获BAT等offer,分享我这两年的经验和感悟
微信公众号[程序员江湖] 作者黄小斜,斜杠青年,某985硕士,阿里 Java 研发工程师,于 2018 年秋招拿到 BAT 头条.网易.滴滴等 8 个大厂 offer,目前致力于分享这几年的学习经验. ...
- 最好用的编辑器之一:Vim-Go环境搭建
本文由Librant发表 如果说在Linux环境下,什么编辑器最好用,如果我说是VIM,估计会有一大部分人嗤之以鼻,怎么可能.VIM可能是他用过众多编辑器最难用的一个.在我司用的是云虚拟机,说实话吧, ...