首页 > 解决方案 > 如何自动分页而不是在烧瓶中使用限制和偏移量

问题描述

我希望每页有 25 行,并且应该有一种方法可以访问上一页和下一页。下面是我写的代码。我尝试使用限制和偏移,但后来我不知道如何在 url 中使用它,这也会变得非常复杂。

我尝试在 stackoverflow 上关注多个帖子,但无法获得帮助。

对结果、偏移量和限制进行分页

我只需要知道需要做什么,我会自己做

def api_split(le):
a="%s,"*le
return a[:-1]

def app_complex_split(st,obj):
    s=""
    if st=="topic":
        for _ in range(len(obj)):
            s+=' bsub.name like %s COLLATE utf8_general_ci or bs.name like %s COLLATE utf8_general_ci or'
        return s[:-3]
    elif st=="author":
        for _ in range(len(obj)):
            s+=' a.name like %s COLLATE utf8_general_ci or'
        return s[:-3]
    elif st=="title":
        for _ in range(len(obj)):
            s+=' b.title like %s COLLATE utf8_general_ci or'
        return s[:-3]


@app.route('/api/v1/books', methods=['GET'])
def api_specific():
    conn = mysql.connector.connect(CONNECTION_DETAILS)
    query_parameters = request.args
    #prev = query_parameters.get('prev')
    #next = query_parameters.get('next')
    book_id = query_parameters.get('book_id')
    lang = query_parameters.get('lang')
    mime_type = query_parameters.get('mime_type')
    topic = query_parameters.get('topic')
    author = query_parameters.get('author')
    title = query_parameters.get('title')

    query = '''SELECT SQL_CALC_FOUND_ROWS b.title "title",a.name "author",b.media_type "genre",GROUP_CONCAT(DISTINCT l.code) "language",GROUP_CONCAT(DISTINCT bsub.name) "subject(s)",GROUP_CONCAT(DISTINCT bs.name) "bookshelf(s)",GROUP_CONCAT(DISTINCT f.url) "links"
    FROM books_book b
inner join books_book_authors ba on b.id=ba.book_id
inner join books_author a on a.id=ba.author_id
inner join books_book_bookshelves bss on ba.book_id=bss.book_id
inner join books_bookshelf bs on bss.bookshelf_id=bs.id
inner join books_book_subjects bsubs on bsubs.book_id=ba.book_id
inner join books_subject bsub on bsubs.subject_id=bsub.id
inner join books_format f on f.book_id=ba.book_id
inner join books_book_languages ls on ls.book_id=ba.book_id
inner join books_language l on ls.language_id=l.id
where'''
    to_filter = tuple()
    if book_id:
        book_var=tuple(book_id.split(","))
        query += ' b.gutenberg_id in ('+api_split(len(book_var))+') AND'
        to_filter+=book_var
    if lang:
        lang_var=tuple(lang.split(","))
        query += ' l.code in ('+api_split(len(lang_var))+') AND'
        to_filter+=lang_var
    if mime_type:
        if ',' in mime_type:
            mime_type_var=tuple(mime_type.split(","))
        else:
            mime_type_var=tuple(mime_type)
        query += ' f.mime_type in ('+api_split(len(mime_type_var))+') AND'
        to_filter+=mime_type_var
    if topic:
        topic_var=tuple(topic.split(","))
        query += app_complex_split("topic",topic_var)+' AND'
        topic_var=list(topic_var)
        for item in range(len(topic_var)):
            topic_var[item]="%"+topic_var[item]+"%"
        topic_var2=tuple(topic_var)*2
        to_filter+=topic_var2
    if author:
        author_var=tuple(author.split(","))
        query += app_complex_split("author",author_var)+' AND'
        author_var=list(author_var)
        for item in range(len(author_var)):
            author_var[item]="%"+author_var[item]+"%"
        author_var2=tuple(author_var)
        to_filter+=author_var2
    if title:
        title_var=tuple(title.split(","))
        query += app_complex_split("title",title_var)+' AND'
        title_var=list(title_var)
        for item in range(len(title_var)):
            title_var[item]="%"+title_var[item]+"%"
        title_var2=tuple(title_var)
        to_filter+=title_var2

    query = query[:-4]

    query+=''' GROUP by b.title,a.name,b.media_type order by b.download_count desc LIMIT 25 OFFSET 0;'''
    if conn.is_connected():
        cursor = conn.cursor(dictionary=True)
        cursor.execute(query,to_filter)
        record = cursor.fetchall()
        cursor.execute('SELECT FOUND_ROWS() "count";')
        count=cursor.fetchall()
        t={}
        t.update(count[0])
        t["result"]=record
        #t=count+t
    conn.close()
    return jsonify(t)

标签: pythonmysqlflask

解决方案


知道每页需要多少行是完美的,但是您需要对其进行抛光并了解flask 中的表单发布请求。您不需要制作表单,但您需要了解如何将页码传递回服务器。假设客户端将访问 api_specific 路由:

/api/v1/books?pg=PAGE_NUMBER_GOES_HERE

在 SQL 方面,将 SQL_CALC_FOUND_ROWS 替换为

COUNT(book_id) AS book_count

因为它更快。假设我们在一个查询中收集了所有书籍,第一页的 book_count 值应该在 0 到 25 之间,第二页的 book_count 值应该在 25 到 50 之间,等等。这就是您需要输入的地方来自用户:知道他们在哪个页面上。(它比看起来更容易,您也可以将分页按钮与页码一起转换为指向路由 url 的链接)。

获得页码后,您想将该值乘以 25。这将是我们正在搜索的最大 book_count 值。从产品中减去 25,您就有了下限!

这是您可以尝试的结构。

SELECT book_name, col_var, other_vat ,(SELECT max(book_id) FROM TableNameHere WHERE ... AND COUNT(book_id) = (25* (PAGE#-1)) as lower_bound FROM books WHERE LIMIT 25 OFFSET lower_bound;

本质上,我们找到最大的 book_id(通过遍历数据库直到找到 25* (PAGE#-1) 个值找到的最后一个 id,然后通过在索引处偏移并继续搜索不超过 25 个有效行来开始第二个查询。


推荐阅读