python - 如何自动分页而不是在烧瓶中使用限制和偏移量
问题描述
我希望每页有 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)
解决方案
知道每页需要多少行是完美的,但是您需要对其进行抛光并了解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 个有效行来开始第二个查询。
推荐阅读
- javascript - 是的,使用新的验证字段更新架构
- android - android 2-way data-binding kotlin mthod没有被调用
- c# - 使用原始请求标头 C# 在请求正文中发送参数和文件
- sql-server - T-SQL 将 XML 数据解析为单行
- ios - 即使正确设置,也隐藏在 ViewController 中的大标题
- intellij-idea - 如何通过右键单击在 Intellij 中运行 .sh?
- docker - 如何将我的代码安装到容器中,然后运行它?
- jsf - 禁用/启用primefaces keyFilter
- postgresql - Postgres 查询有时需要很长时间
- json - 使用 Helm 创建包含引用元素列表的 json 可解析 k8s 配置映射