zoukankan      html  css  js  c++  java
  • Flask 系列之 Pagination

    说明

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

    实验目标

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

    实现

    首先,在我们的 todolistforms.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('提交')
    

    接着修改 todolistappviews.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'))
    

    最后,完善 todolistapp emplatesindex.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]
  • 相关阅读:
    NOI 2016 区间 解题报告
    有关莫队
    [JSOI2008]最大数 线段树解法
    HDU P3341 Lost's revenge 题解+数据生成器
    BZOJ P1212 [HNOI2004] L语言
    洛谷P3168 [CQOI2015]任务查询系统
    普通平衡树Tyvj1728、luogu P3369 (splay)
    洛谷P3384 树链剖分
    BZOJ P2157 旅游
    【算法导论】第6章,堆排序
  • 原文地址:https://www.cnblogs.com/hippieZhou/p/10605831.html
Copyright © 2011-2022 走看看