Курсор хранилища данных GCP такой же - PullRequest
0 голосов
/ 16 июня 2020

Я выполняю разбиение на страницы с помощью Flask и GCP Datastore, но у меня проблема с курсором, когда я нажимаю на следующую страницу, курсор остается прежним, когда я нажимаю на другие страницы. Например, когда я щелкаю страницу 10 со страницы 9, поскольку курсор остается прежним, он по-прежнему отображает то же содержимое, что и на странице 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 %}

1 Ответ

0 голосов
/ 17 июня 2020

Google рекомендует использовать курсоры вместо целочисленных смещений из-за операций чтения, выполняемых клиентской библиотекой, и я цитирую:

Хотя базы данных в режиме Datastore поддерживают целочисленные смещения, вам следует избегать их использования. Вместо этого используйте курсоры. Использование смещения только позволяет избежать возврата пропущенных сущностей в ваше приложение, но эти сущности по-прежнему извлекаются изнутри. Пропущенные сущности влияют на задержку запроса, и вашему приложению выставляется счет за операции чтения, необходимые для их получения. Использование курсоров вместо смещений позволяет избежать всех этих затрат.

Я бы рекомендовал вам быть осторожным с тем, как вы устанавливаете курсор и какая информация передается (я бы посоветовал вам отладить и протестируйте код, указанный ниже)

Будьте осторожны при передаче курсора клиенту, например, в веб-форме. Хотя клиент не может изменить значение курсора для доступа к результатам за пределами исходного запроса, он может декодировать курсор для предоставления информации о сущностях результата, такой как идентификатор проекта, тип сущности, имя ключа или число c ID. , ключи предков и свойства, используемые в фильтрах и порядках сортировки запроса. Если вы не хотите, чтобы пользователи имели доступ к этой информации, вы можете зашифровать курсор или сохранить его и предоставить пользователю непрозрачный ключ.

то, что, по моему мнению, вызывает у вас проблемы с вашим реализация

Теперь, говоря о реализации этого с помощью курсоров, есть небольшой фрагмент официальной документации или, если вы предпочитаете взглянуть на это в официальном репозитории github , вы можете go здесь

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
...