我正在使用Flask和GCP数据存储进行分页,但是单击下一页时光标出现问题,单击其他页面时光标仍然相同。例如,当我单击第9页上的第10页时,由于光标仍然相同,所以它仍显示第9页上的相同内容。谢谢,如何解决此问题?这是我的代码。
@bp.route('/selectimage/<dataset_name>/<dataset_id>/<startdate>/<enddate>/', methods=["POST", "GET"])
def selectimage(dataset_id, dataset_name, startdate, enddate):
photo = {}
startdate = int(startdate)
enddate = int(enddate)
dataset_id = dataset_id
dataset_name = dataset_name
request_arg = request.args
if "page" in request_arg:
total_row = request_arg.get('total_row')
page = request_arg.get('page')
total_page = request_arg.get('total_page')
total_page_range = range(0, int(total_page))
if page == '1':
# get result
photometa_data_results = datastore_client.query(kind='photometadata')
photometa_data_results.add_filter('Time', '>=', startdate)
photometa_data_results.add_filter('Time', '<=', enddate)
photometa_data_results.order = ['-Time'] # order by time
photometa_data_results = photometa_data_results.fetch(limit=40)
result = list(next(photometa_data_results.pages))
else:
page_limit = (int(page) - 1) * 40
# get first cursor
query_photometa_data_cursor = datastore_client.query(
kind='photometadata') # query photometadata grap by instagram
query_photometa_data_cursor.add_filter('Time', '>=', startdate)
query_photometa_data_cursor.add_filter('Time', '<=', enddate)
query_photometa_data_cursor.order = ['-Time'] # order by time
photometa_data_results_cursor_1 = query_photometa_data_cursor.fetch(start_cursor=None,
limit=360) # result of query photometadata table
photometa_data_results_page = next(photometa_data_results_cursor_1.pages)
photometa_data_results_cursor = photometa_data_results_cursor_1.next_page_token
# get result
photometa_data_results = datastore_client.query(kind='photometadata')
print(photometa_data_results_cursor)
photometa_data_results.add_filter('Time', '>=', startdate)
photometa_data_results.add_filter('Time', '<=', enddate)
photometa_data_results.order = ['-Time'] # order by time
photometa_data_results = photometa_data_results.fetch(start_cursor=photometa_data_results_cursor, limit=40)
result = list(next(photometa_data_results.pages))
print(result)
else:
page = 1
# get how many pages
photometa_data_pages = datastore_client.query(kind='photometadata')
photometa_data_pages.add_filter('Time', '>=', startdate)
photometa_data_pages.add_filter('Time', '<=', enddate)
photometa_data_pages.order = ['-Time'] # order by time
photometa_data_pages_result = list(photometa_data_pages.fetch())
total_row = (len(photometa_data_pages_result))
total_page = math.ceil(len(photometa_data_pages_result) / 40)
total_page_range = range(0, total_page)
# get_result
photometa_data = datastore_client.query(kind='photometadata')
photometa_data.add_filter('Time', '>=', startdate)
photometa_data.add_filter('Time', '<=', enddate)
photometa_data.order = ['-Time'] # order by time
photoinfo = photometa_data.fetch(limit=40)
result = list(next(photoinfo.pages))
next_cursor = photoinfo.next_page_token
query_dataset_photo = datastore_client.query(kind='Datasetphotos') # query dataset photo table
query_dataset_photo.add_filter('Dataset_id', '=', dataset_id)
query_dataset_photo_list_result = list(query_dataset_photo.fetch()) # list query result
dataset_photo_namelist = []
if query_dataset_photo_list_result != []:
for dataset_photo_filename in query_dataset_photo_list_result:
dataset_photo_namelist.append(dataset_photo_filename['Filename'])
if result == []:
flash('No photo', category='info')
else:
for results in result:
time = datetime.fromtimestamp(results['Time'])
photo[results['Filename']] = {'Filename': results['Filename'], "Url": results['Gcs_public_url'],
"Time": time,
'Link': results["Link"]}
totoalphoto = len(photo)
# get the ticked photo
upload_data_list = []
check_name_list = []
if request.form.getlist('images'):
images = request.form.getlist('images') # get the image from ticked form
for image in images:
querys = datastore_client.query(kind='photometadata')
querys.add_filter('Filename', '=', image)
datas = list(querys.fetch())
for data in datas:
name = dataset_id + ':' + data['Filename']
if data['Filename'] in check_name_list:
pass
else:
upload_datas = {
'Filename': data['Filename'],
"PostID": data['PostID'],
"Storage_url": data['Storage_url'],
"Gcs_public_url": data['Gcs_public_url'],
"Url": data['Url'],
'Dataset_id': dataset_id,
'Link': data['Link'],
"Time": data['Time'],
'Upload_date': datetime.today().strftime('%Y-%m-%d %H:%M'),
}
check_name_list.append(data['Filename'])
upload_data_list.append(upload_datas)
upload_data_lists = [upload_data_list[i:i + 499] for i in
range(0, len(upload_data_list), 499)]
for upload_data_list in upload_data_lists:
batch = datastore_client.batch()
kind = 'evaluation_dataset_photo'
batch.begin()
for upload_data in upload_data_list:
name = upload_data['check_name']
data_key = datastore_client.key(kind, name)
task = datastore.Entity(key=data_key, exclude_from_indexes=['Url', 'Gcs_public_url'])
task.update(upload_data)
batch.put(task)
batch.commit()
number = len(images) # number of upload photo
message = 'Uploaded ' + str(number) + ' photo to ' + dataset_name # number of photo upload
flash(message, category='success')
logging.info(message)
return redirect('/selectimage/{}/{}/{}/{}/{}'.format(dataset_name, dataset_id, startdate, enddate))
return render_template('selectimage.html', dataset_name=dataset_name, photo=photo,
totoalphoto=totoalphoto, page=page, total_page_range=total_page_range,
total_page_range_count=total_page
, total_row=total_row, dataset_id=dataset_id, startdate=startdate, enddate=enddate)
前端代码
{% extends "base.html" %}
{% block scripts %}
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='flask.css') }}">
{{ super() }}
{% endblock %}
{% block app_content %}
<div class="page-header" xmlns="http://www.w3.org/1999/html">
<h1>Add image</h1>
<b><h1>Dataset:{{ dataset_name }} Photo:{{ total_row }}</h1></b>
<div class="col-md-2" id="client-paginator">
<ul class="pagination">
{% for total_pages in total_page_range %}
<li>
<a href="/selectimage/{{ dataset_name }}/{{ dataset_id }}/{{ startdate }}/{{ enddate }}?page={{ total_pages + 1 }}&total_page={{ total_page_range_count }}&total_row={{ total_row }}">
{{ total_pages + 1 }}
</a>
</li>
{% endfor %}
</ul>
</div>
</div>
{% if photo != {} %}
<form id='assignimage' action="" method="POST">
<div align="left"><input style="heightx: 15%;width: 15%" class="btn-success" type="submit" value="Add">
</div>
{% for k,v in photo.items() %}
<div class="col-md-3">
<img src="{{ v['Url'] }}" style="display:block; margin-right: auto;margin-left: auto"
width="330px" height="330px">
<div style="margin-left: auto;margin-right: auto;width: 20em;text-align: center">
<input type="checkbox" name="images" value="{{ v['Filename'] }}">
{{ v['Time'] }}
<a href="{{ v['Link'] }}" class="glyphicon glyphicon-new-window" target="_blank"></a></div>
<hr>
</div>
{% endfor %}
</form>
</div>
{% endif %}
{% endblock %}
Google推荐使用游标而不是整数偏移量,因为客户端库正在执行读取操作,我引用:
尽管数据存储模式数据库支持整数偏移量,但您应该 避免使用它们。而是使用游标。仅使用偏移量可以避免 将跳过的实体返回到您的应用程序,但是这些实体 仍在内部检索。跳过的实体确实会影响 查询的延迟,并且您的应用需要为读取付费 检索它们所需的操作。使用游标而不是偏移量 让您避免所有这些费用。
您可以查看此信息here(它也包含一个小的实现)
现在谈论使用游标的实现,official documentation上有一个小片段,或者如果您想在官方的github repo, you can go here上看一下此内容,>
def cursor_paging(client):
# [START datastore_cursor_paging]
def get_one_page_of_tasks(cursor=None):
query = client.query(kind='Task')
query_iter = query.fetch(start_cursor=cursor, limit=5)
page = next(query_iter.pages)
tasks = list(page)
next_cursor = query_iter.next_page_token
return tasks, next_cursor
# [END datastore_cursor_paging]
page_one, cursor_one = get_one_page_of_tasks()
page_two, cursor_two = get_one_page_of_tasks(cursor=cursor_one)
return page_one, cursor_one, page_two, cursor_two