15、flask-模型-models-表的操作-分頁paginate()

little小新發表於2024-07-27

paginate()的屬性

屬性名 說明
items 返回當前頁的內容列表
has_next 是否還有下一頁
has_prev 是否還有上一頁
next(error_out=False) 返回下一頁的pagination物件
prev(error_out=False) 返回上一頁的Pagination物件
page 當前頁的頁碼
pages 總頁數
per_page 每頁顯示的數量
prev_num 上一頁頁碼數
next_num 下一頁頁碼數
total 查詢返回記錄總數

案例1 - 屬性的使用

# 分頁,翻頁
# 方案1. 手動翻頁
#  offset(): 查詢指定條數,從指定位置開始
#  limit(): 查詢指定條數
#  page=1 頁碼
# 每頁顯示的數量:per_page=5
# page=1:1 2 3 4 5  => offset(0).limit(5)
# page=2:6 7 8 9 10 => offset(5).limit(5)
# page=3:11 12 13 14 15 => offset(10).limit(5)
# page=4:16 17 18 19 20 => offset(15).limit(5)
# ...
# page=n:     => offset((page-1)*per_page).limit(per_page)

# 方案2.paginate 翻頁
@blue.route('/paginate/')
def get_paginate():
    # 頁碼:如果沒有傳page引數預設值為1
    page = int(request.args.get('page', 1))
    # per_page:每頁顯示的數量,預設每頁顯示5條資料
    per_page = int(request.args.get('per_page', 5))
    # print(page, type(page))
    # print(per_page, type(per_page))

    # paginate()
    p = User.query.paginate(page=page, per_page=per_page, error_out=False)
    print(p.items)  # 列印當前頁的資料
    print(p.has_next)   # 是否有下一頁
    print(p.has_prev)   # 是否有上一頁
    print(p.next(error_out=False).items)  # 返回下一頁的pagination的物件 加上items屬性表示當前頁的資料
    print(p.prev(error_out=False).items)  # 返回上一頁的pagination的物件
    print(p.page)   # 當前頁碼 從1開始
    print(p.pages)  # 總頁數
    print(p.per_page)   # 每頁顯示的數量
    print(p.prev_num)   # 上一頁頁碼數
    print(p.next_num)   # 下一頁頁碼數
    print(p.total)  # 總條數

    return render_template('paginate.html')

    # 瀏覽器:http://localhost:5000/paginate/?page=2&per_page=4 傳參

案例2 - 結合前端展示

擴充套件 - 前端渲染

參考bootstrap官網

使用bootstrap樣式:
列表渲染

分頁按鈕渲染:

以下是程式碼:

app.py

from App import create_app

app = create_app()

if __name__ == '__main__':
    app.run(debug=True)

# 執行: flask run --debug

views.py

from flask import Blueprint, request, render_template
from sqlalchemy import desc, and_, or_, not_

from .models import *

#建立藍圖(路由)
blue = Blueprint('user', __name__)

@blue.route('/')
def index():
    return 'index'


# 建立物件: 物件名(自定義) = 類名()     -- > 該物件指的是models中的類
# 物件.屬性名 = 表欄位的值

# 單表操作 - 增刪改查
# 1.增
@blue.route('/useradd/')
def user_add():
    # #新增一條資料
    # # 建立物件
    # user = User()
    # user.name = '張三'
    # user.age = 18
    # db.session.add(user)    #將物件user新增到session中
    # db.session.commit()     #將session中的資料提交到資料庫中

    #新增多條資料
    users = []
    for i in range(10, 30):
        user = User()
        user.name = '張' + str(i)
        user.age = i
        users.append(user)

    try:
        db.session.add_all(users)    #將物件user新增到session中, all新增多個物件
        db.session.commit()     #將session中的資料提交到資料庫中  事務提交
    except Exception as e:
        db.session.rollback()   #回滾
        db.session.flush()  #清空session
        return '新增失敗' + str(e)
        #因為這裡name是唯一值、所以如果重複新增會報錯,將錯誤列印出來
    return '新增成功'


# 2.刪
# 先查到要刪除的資料,再執行刪除
@blue.route('/userdel/')
def user_del():
    # 先查到要刪除的資料
    user = User.query.first()   #查詢第一條資料
    db.session.delete(user)
    db.session.commit()

    return '刪除成功'

# 3.改
@blue.route('/userupdate/')
def user_update():
    # 先查到要修改的資料
    user = User.query.first()
    user.age = 200
    db.session.commit()
    return '修改成功'

# 4.查
@blue.route('/userget/')
def user_get():
    # all(): 查詢所有資料
    users = User.query.all()    #查詢所有資料
    # print(users)    #列印的是物件、如果models中有__repr__方法,列印的是物件的屬性值、如果沒有__repr__方法,列印的是物件的記憶體地址
    # print(User.query)   #列印的是sql語句

    # filter(): 過濾, 過濾條件,類似where 、支援鏈式查詢、得到的是查詢集
    users = User.query.filter()
    # print(users)

    # get(): 根據主鍵查詢、如果沒有找到,返回None、
    user = User.query.get(10)
    # print(user)
    # print(user.name, user.age)  # 列印物件的屬性值


    # filter()與filter_by()的區別
    # filter()  # 類似where、支援不等值的條件查詢、但條件要:物件.屬性名
    # filter_by()   #用於等值 = 操作的過濾條件,而不支援 > < 等不等值的條件查詢

    # users = User.query.filter(User.age==18)   #
    #users = User.query.filter(User.age>18)     #返回的是查詢集

    users = User.query.filter_by(age=18)        #可以直接屬性值查詢
    # users = User.query.filter_by(age>18)      #這是不支援的所以會報錯
    # print(list(users))  # 列印查詢集使用list()強轉列印


    # first(): 查詢第一條資料
    # last(): 查詢最後一條資料
    user = User.query.first()
    # user = User.query.last()
    user = User.query.first_or_404()
    print(user.name, user.age)


    # count(): 查詢資料條數
    count = User.query.count()
    print(count)

    # limit(): 查詢指定條數
    # offset(): 查詢指定條數,從指定位置開始
    users = User.query.offset(3).limit(4)
    print(list(users))

    # order_by(): 排序
    users = User.query.order_by('age')  # 升序
    users = User.query.order_by(desc('age'))  # 降序  需要匯入 from sqlalchemy import desc
    print(list(users))

    # 邏輯運算 and_ , or_ , not_
    users = User.query.filter(User.age>20, User.age<30) # 且運算
    users = User.query.filter(and_(User.age>20, User.age<30))
    users = User.query.filter(or_(User.age>20, User.age<30))
    users = User.query.filter(not_(User.age>20))
    print(list(users))

    # 查詢屬性
    users = User.query.filter(User.name.contains('張'))  # 模糊查詢 類似 like
    # in_() : 查詢屬性
    users = User.query.filter(User.name.in_(['張三', '李四']))  # 查詢在列表中的資料
    # startswith(): 查詢以什麼開頭的資料
    users = User.query.filter(User.name.startswith('張'))
    # endswith(): 查詢以什麼結尾的資料
    users = User.query.filter(User.name.endswith('三'))

    # __gt__: 大於
    # __lt__: 小於
    # __ge__: 大於等於
    # __le__: 小於等於
    users = User.query.filter(User.age.__gt__(20))
    users = User.query.filter(User.age.__ge__(20))
    users = User.query.filter(User.age.__le__(20))
    print(list(users))


    return '查詢成功'


# 分頁,翻頁
# 方案1. 手動翻頁
#  offset(): 查詢指定條數,從指定位置開始
#  limit(): 查詢指定條數
#  page=1 頁碼
# 每頁顯示的數量:per_page=5
# page=1:1 2 3 4 5  => offset(0).limit(5)
# page=2:6 7 8 9 10 => offset(5).limit(5)
# page=3:11 12 13 14 15 => offset(10).limit(5)
# page=4:16 17 18 19 20 => offset(15).limit(5)
# ...
# page=n:     => offset((page-1)*per_page).limit(per_page)

# 方案2.paginate 翻頁
@blue.route('/paginate/')
def get_paginate():
    # 頁碼:如果沒有傳page引數預設值為1
    page = int(request.args.get('page', 1))
    # per_page:每頁顯示的數量,預設每頁顯示5條資料
    per_page = int(request.args.get('per_page', 5))
    # print(page, type(page))
    # print(per_page, type(per_page))

    # paginate()
    p = User.query.paginate(page=page, per_page=per_page, error_out=False)
    print(p.items)  # 列印當前頁的資料
    print(p.has_next)   # 是否有下一頁
    print(p.has_prev)   # 是否有上一頁
    print(p.next(error_out=False).items)  # 返回下一頁的pagination的物件 加上items屬性表示當前頁的資料
    print(p.prev(error_out=False).items)  # 返回上一頁的pagination的物件
    print(p.page)   # 當前頁碼 從1開始
    print(p.pages)  # 總頁數
    print(p.per_page)   # 每頁顯示的數量
    print(p.prev_num)   # 上一頁頁碼數
    print(p.next_num)   # 下一頁頁碼數
    print(p.total)  # 總條數

    return render_template('paginate.html', p=p)    # 渲染模板 , p表示pagination的物件

    # 瀏覽器:http://localhost:5000/paginate/?page=2&per_page=4 傳參

models.py

# 模型資料庫

from .exts import db    #匯入db物件

# 模型     對應資料庫中的     資料庫
# 類名                      表             (對錶操作就是對類操作)
# 物件(變數值)               表的一行資料
# 類屬性(變數名)             表欄位

# 建立物件: 物件名(自定義) = 類名()
# 物件.屬性名 = 表欄位的值


# 模型: 類名
# 必須繼承:db.Model  才是 一個模型
class User(db.Model):
    # 表名
    __tablename__ = 'user'
    # 欄位
    id = db.Column(db.Integer, primary_key=True, autoincrement=True)
    name = db.Column(db.String(50), unique=True)
    age = db.Column(db.Integer, default=1)

    # 列印物件的名字
    def __repr__(self):
        return self.name    # 返回物件的名字


# db.Column :表示欄位
# db.Integer :表示欄位的型別 整數型別
# primary_key=true : 表示主鍵
# autoincrement=true : 表示自增
# db.String(50) : 表示欄位的長度 相當於varchar(50)
# index=True : 表示建立索引
# db.Boolean : 表示布林型別
# default=1 : 表示預設值
# db.Float : 表示浮點型別
# nullable=False : 表示不能為空

exts.py

from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

#初始化外掛
db = SQLAlchemy()
migrate = Migrate()

#和app物件繫結
def init_exts(app):
    db.init_app(app)
    migrate.init_app(app,db)

__init__.py

from flask import Flask
from .views import blue
from .exts import init_exts


def create_app():
    app = Flask(__name__)   # 建立flask應用

    #註冊藍圖
    app.register_blueprint(blueprint=blue)

    #配置資料庫
    db_uri = 'sqlite:///sqlite3.db'     #sqlite的配置
    # db_uri = 'mysql+pymysql://root:123456@127.0.0.1:3306/flask_db?charset=utf8mb4'  #mysql的配置
    app.config['SQLALCHEMY_DATABASE_URI'] = db_uri
    app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

    #初始化外掛
    init_exts(app=app)

    return app

paginate.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>分頁功能</title>
    {# 這裡引入bootstrap樣式 參考官網:https://v4.bootcss.com/docs/getting-started/introduction/ #}
    <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css" integrity="sha384-xOolHFLEh07PJGoPkLv1IbcEPTNtaed2xpHsD9ESMhqIYd0nLMwNLD69Npy4HI+N" crossorigin="anonymous">

</head>
<body>

<div class="container">
    <h2>分頁功能</h2>
    <hr>

    {#  資料的展示  #}
    <ul class="list-group">
        {#  views.py檢視函式中傳過來的是 paginate物件,所以可以使用paginate物件的所有的屬性 #}
        {% for user in p.items %}
            <li class="list-group-item">
                {{ user.name }}
            </li>
        {% endfor %}
    </ul>
    <hr>

    {#  頁尾的分頁功能  #}
    <ul class="pagination">
        {# 上一頁 #}
        <li class="page-item">
            {% if p.has_prev %} {# 如果有上一頁,就翻頁 #}
                <a class="page-link" href="/paginate/?page={{ p.prev_num }}&per_page=3" aria-label="Previous">
            {% else %}  {# 如果沒有上一頁,就禁用 #}
                 <a class="page-link" href="javascript:;" aria-label="Previous">
            {% endif %}
                <span aria-hidden="true">&laquo;</span>
            </a>
        </li>

        {% for i in range(p.pages) %}
            {# 選中頁碼高亮 #}
            {% if p.page == i + 1 %}
                <li class="page-item active">
            {% else %}
                <li class="page-item">
            {% endif %}
                {# href="/paginate/?page={{ i + 1 }}" 點選頁碼跳轉  &per_page=3固定頁碼數 #}
                <a class="page-link" href="/paginate/?page={{ i + 1 }}&per_page=3">{{ i + 1 }}</a>
            </li>
        {% endfor %}

        {# 下一頁 #}
        <li class="page-item">
            {% if p.has_next %}
                <a class="page-link" href="/paginate/?page={{ p.next_num }}&per_page=3" aria-label="Next">
            {% else %}
                <a class="page-link" href="javascript:;" aria-label="Next">
            {% endif %}
                <span aria-hidden="true">&raquo;</span>
            </a>
        </li>


    </ul>


</div>

</body>
</html>

目錄如下:

展示:

相關文章