Google app engine 使用光标反向分页正在工作,但缺少一项

Google app engine 使用光标反向分页正在工作,但缺少一项,google-app-engine,app-engine-ndb,Google App Engine,App Engine Ndb,从中,我可以找到一个提示,如何通过颠倒顺序使用单个光标反向页面导航 class CursorTests(test_utils.NDBTest): def testFirst(self): class Bar(model.Model): value = model.IntegerProperty() self.entities = [] for i in range(10): e = Bar(value=i) e.put(

从中,我可以找到一个提示,如何通过颠倒顺序使用单个光标反向页面导航

class CursorTests(test_utils.NDBTest):

  def testFirst(self):
    class Bar(model.Model):
      value = model.IntegerProperty()

    self.entities = []
    for i in range(10):
        e = Bar(value=i)
        e.put()
        self.entities.append(e)

    q = Bar.query()
    bars, next_cursor, more = q.order(Bar.key).fetch_page(3)
    barz, another_cursor, more2 = q.order(-Bar.key).fetch_page(3, start_cursor=next_cursor)
    self.assertEqual(len(bars), len(barz))
不幸的是,它失败了,出现了这个错误

回溯(最近一次调用上次):文件 “/Users/reiot/Documents/Works/appengine-ndb-experience/ndb/query\u-test.py”, 第32行,在testFirst中 self.assertEqual(len(bar),len(baz))断言者错误:3!=二,

是,反向查询中缺少边界中的项

bars = [Bar(key=Key('Bar', 1), value=0), Bar(key=Key('Bar', 2), value=1), Bar(key=Key('Bar', 3), value=2)] 
bars = [Bar(key=Key('Bar', 2), value=1), Bar(key=Key('Bar', 1), value=0)]

如何解决这个问题?

好的,这是正式的答案。您需要“反转”光标,如下所示:

rev_cursor = cursor.reversed()

我自己也不知道-(我将确保在fetch_page()的文档中显示这一点。

处理这些多个游标,加上正向和反向查询不仅太复杂,而且不允许直接分页(转到第7页),页面底部有一组页面链接,如“>”,因为您不知道将有多少页面

出于这个原因,我的解决方案是获取整个结果集,或者至少是一个重要的结果集,例如对应于10个页面,然后进行简单的划分来处理页面,首先使用
keys_only=True
获取结果。确定与当前页面对应的集合后,执行
key.get()在您的实体上。如果您愿意,可以考虑在MyC缓存中保存完整的密钥列表几分钟,这样查询就不会重新运行,尽管到目前为止我还没有发现这是必要的。
这是一个示例实现:

def session_list():
    page = request.args.get('page', 0, type=int)

    sessions_keys = Session.query().order(-Session.time_opened).fetch(100, keys_only=True)
    sessions_keys, paging = generic_list_paging(sessions_keys, page)
    sessions = ndb.get_multi(sessions_keys)

    return render_template('generic_list.html', objects=sessions, paging=paging)
它使用了一个
generic\u list\u paging
函数来进行分页划分,并在结果集中提取适当的子列表:

def generic_list_paging(objects, page, page_size=10):
    nb_items = len(objects)
    item_start = min(page * page_size, nb_items)
    item_end = min((page + 1) * page_size, nb_items)
    page_max = (nb_items - 1) // page_size + 1
    objects = objects[item_start: item_end]
    paging = {'page': page, 'page_max': page_max}
    return objects, paging
最后,如果您使用的是Jinja2,下面是使用
paging
dict的分页导航:

{% if paging.page_max > 1 %}
        <nav>
            <ul class="pagination">
                {% if paging.page > 0 %}
                    <li>
                        <a href="{{ request.path }}?page={{ paging.page-1 }} aria-label="Previous">
                            <span aria-hidden="true">&laquo;</span>
                        </a>
                    </li>
                {% endif %}
                {% for page in range(0,paging.page_max) %}
                    <li {% if page==paging.page %}class="disabled"{% endif %}><a href="{{ request.path }}?page={{ page }}">{{ page+1 }}</a></li>
                {% endfor %}
                {% if paging.page < paging.page_max-1 %}
                    <li>
                        <a href="{{ request.path }}?page={{ paging.page+1 }}" aria-label="Next">
                            <span aria-hidden="true">&raquo;</span>
                        </a>
                    </li>
                {% endif %}
            </ul>
        </nav>
{% endif %}
{%if paging.page_max>1%}
    {%如果paging.page>0%}
  • {%endif%} {范围(0,paging.page_max)%%内的页的百分比} {%endfor%} {%if paging.page {%endif%}
{%endif%}
问得好。我已经证实了这一点。我已经召集了专家。它在生产数据存储中是否也有这样的行为?这是我从一年开始在文档或新闻中搜索的内容:)文档早就被修复了。在上面的代码中,sessions=[sk.get()for sk In sessions\u keys]在性能方面并不好,它应该是一个get\u multi()。我刚修好。