blob: fdc1fc820a9444b7ee91acb3a9110a78082f8d71 [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>paging</title>
<link rel="stylesheet" href="/css/pycco.css">
</head>
<body>
<div id="background"></div>
<div id='container'>
<div class='section'>
<div class='docs'><h1>paging</h1></div>
</div>
<div class='clearall'>
<div class='section' id='section-0'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-0'>#</a>
</div>
<p>If you have not yet seen the source in <a href="/examples/basic.html">basic</a>, please take a look.</p>
</div>
<div class='code'>
<div class="highlight"><pre></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-1'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-1'>#</a>
</div>
<p>In this sample we modify the query parameters in the <code>MyModelList</code> method to
allow paging through results.</p>
</div>
<div class='code'>
<div class="highlight"><pre></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-2'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-2'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre><span class="kn">import</span> <span class="n">endpoints</span>
<span class="kn">from</span> <span class="nn">google.appengine.ext</span> <span class="kn">import</span> <span class="n">ndb</span>
<span class="kn">from</span> <span class="nn">protorpc</span> <span class="kn">import</span> <span class="n">remote</span>
<span class="kn">from</span> <span class="nn">endpoints_proto_datastore.ndb</span> <span class="kn">import</span> <span class="n">EndpointsModel</span>
<span class="k">class</span> <span class="nc">MyModel</span><span class="p">(</span><span class="n">EndpointsModel</span><span class="p">):</span>
<span class="n">attr1</span> <span class="o">=</span> <span class="n">ndb</span><span class="o">.</span><span class="n">StringProperty</span><span class="p">()</span>
<span class="n">attr2</span> <span class="o">=</span> <span class="n">ndb</span><span class="o">.</span><span class="n">StringProperty</span><span class="p">()</span>
<span class="n">created</span> <span class="o">=</span> <span class="n">ndb</span><span class="o">.</span><span class="n">DateTimeProperty</span><span class="p">(</span><span class="n">auto_now_add</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="nd">@endpoints.api</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">&#39;myapi&#39;</span><span class="p">,</span> <span class="n">version</span><span class="o">=</span><span class="s">&#39;v1&#39;</span><span class="p">,</span> <span class="n">description</span><span class="o">=</span><span class="s">&#39;My Little API&#39;</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">MyApi</span><span class="p">(</span><span class="n">remote</span><span class="o">.</span><span class="n">Service</span><span class="p">):</span>
<span class="nd">@MyModel.method</span><span class="p">(</span><span class="n">path</span><span class="o">=</span><span class="s">&#39;mymodel&#39;</span><span class="p">,</span> <span class="n">http_method</span><span class="o">=</span><span class="s">&#39;POST&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s">&#39;mymodel.insert&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">MyModelInsert</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">my_model</span><span class="p">):</span>
<span class="n">my_model</span><span class="o">.</span><span class="n">put</span><span class="p">()</span>
<span class="k">return</span> <span class="n">my_model</span>
</pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-3'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-3'>#</a>
</div>
<p>To add paging functionality, we set the keyword argument <code>query_fields</code> in the
<code>MyModel.query_method</code> decorator. By specifying the fields <code>limit</code>, <code>order</code>
and <code>pageToken</code> as the query fields, we can accept values specializing the
query before retrieving results from the datastore. Though <code>limit</code>, <code>order</code>
and <code>pageToken</code> are not defined as properties on <code>MyModel</code>, they are included
as helper properties by the base class <code>EndpointsModel</code>.</p>
<p>The three helper properties we use here perform the following</p>
<ul>
<li><code>limit</code>: Allows a limit to be set for the number of results retrieved by a
query.</li>
<li><code>order</code>: This allows the result set to be ordered by properties. For
example, if the value of <code>order</code> is <code>'attr1'</code>, results of the query
will be in ascending order, ordered by <code>attr1</code>. Similarly, if the
value of <code>order</code> is <code>'-attr2'</code>, the results of the query will be in
descending order, ordered by <code>attr2</code>.<br><br>
Even more complex orders can be created, such as <code>'attr1,-attr2'</code>,
which will first order by <code>attr1</code> and then within each value order by
<code>attr2</code>. However, such queries are not possible in the datastore if
no index has been built. See <a href="/examples/custom_alias_properties.html">custom_alias_properties</a> and
<a href="/examples/matching_queries_to_indexes.html">matching_queries_to_indexes</a> for examples of how to deal with complex
queries.</li>
<li><code>pageToken</code>: This is used for paging within a result set. For example, if a
<code>limit</code> of <code>10</code> is set, but there are <code>12</code> results, then the ProtoRPC
response will have <code>items</code> with <code>10</code> values and a <code>nextPageToken</code>
which contains a string cursor for the query. By using this
value as <code>pageToken</code> in a subsequent query, the remaining <code>2</code>
results can be retrieved and the ProtoRPC response will not
contain a <code>nextPageToken</code> since there are no more results.</li>
</ul>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="nd">@MyModel.query_method</span><span class="p">(</span><span class="n">query_fields</span><span class="o">=</span><span class="p">(</span><span class="s">&#39;limit&#39;</span><span class="p">,</span> <span class="s">&#39;order&#39;</span><span class="p">,</span> <span class="s">&#39;pageToken&#39;</span><span class="p">),</span>
<span class="n">path</span><span class="o">=</span><span class="s">&#39;mymodels&#39;</span><span class="p">,</span> <span class="n">name</span><span class="o">=</span><span class="s">&#39;mymodel.list&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">MyModelList</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">query</span><span class="p">):</span>
<span class="k">return</span> <span class="n">query</span>
</pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-4'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-4'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre>
<span class="n">application</span> <span class="o">=</span> <span class="n">endpoints</span><span class="o">.</span><span class="n">api_server</span><span class="p">([</span><span class="n">MyApi</span><span class="p">],</span> <span class="n">restricted</span><span class="o">=</span><span class="bp">False</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-5'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-5'>#</a>
</div>
<p>For a bit more on the other helper properties provided by <code>EndpointsModel</code>,
see <a href="/examples/simple_get.html">simple_get</a>. To see how to define your own helper properties, see
<a href="/examples/custom_alias_properties.html">custom_alias_properties</a>, <a href="/examples/matching_queries_to_indexes.html">matching_queries_to_indexes</a> and
<a href="/examples/keys_with_ancestors.html">keys_with_ancestors</a>.</p>
<p>To see how query fields can be used to perform simple equality filters, see
<a href="/examples/property_filters.html">property_filters</a>.</p>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-6'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-6'>#</a>
</div>
<p>Head on to the next sample <a href="/examples/property_filters.html">property_filters<a>
or head back to the <a href="/">main page</a>.</p>
</div>
</div>
<div class='clearall'></div>
</div>
</body>