blob: cebb531813460da7d1a893bfe446f9559966e44d [file] [log] [blame]
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="content-type" content="text/html;charset=utf-8">
<title>keys_with_ancestors</title>
<link rel="stylesheet" href="/css/pycco.css">
</head>
<body>
<div id="background"></div>
<div id='container'>
<div class='section'>
<div class='docs'><h1>keys_with_ancestors</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/matching_queries_to_indexes.html">matching_queries_to_indexes</a> and
<a href="/examples/custom_alias_properties.html">custom_alias_properties</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 define an <code>EndpointsAliasProperty</code> which does not override
one of the helper properties provided by <code>EndpointsModel</code>; this is a first as
all the other samples have simply tweaked existing alias properties. We use
this property in conjuction with another alias property to define entity keys
which have an ancestor &mdash; for example
<br><code>ndb.Key(MyParent, ..., MyModel, ...)</code><br>
&mdash; which is slightly more complex than the keys we have seen so far.</p>
<p>We define an extra model <code>MyParent</code> to hold all the data for the ancestors being
used (though this is not strictly necessary, an ancestor key does not need to
exist in the datastore to be used). In addition, since we will be requiring
that a <code>MyParent</code> entity exists to be used as an ancestor, we provide a method
<code>MyParentInsert</code> to allow API users to create or update parent objects.</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></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>See <a href="/examples/matching_queries_to_indexes.html">matching_queries_to_indexes</a> for reference on this import.</p>
</div>
<div class='code'>
<div class="highlight"><pre><span class="kn">from</span> <span class="nn">endpoints_proto_datastore.ndb</span> <span class="kn">import</span> <span class="n">EndpointsAliasProperty</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="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">MyParent</span><span class="p">(</span><span class="n">EndpointsModel</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>As in <a href="/examples/simple_get.html">simple_get</a>, by setting <code>_message_fields_schema</code>, we can set a
custom ProtoRPC message schema. We set the schema to the alias property
<code>name</code> and ignore the NDB property <code>updated</code>.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">_message_fields_schema</span> <span class="o">=</span> <span class="p">(</span><span class="s">&#39;name&#39;</span><span class="p">,)</span>
</pre></div>
</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>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">updated</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</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-7'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-7'>#</a>
</div>
<p>This is a setter which will be used by the alias property <code>name</code>.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">NameSet</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-8'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-8'>#</a>
</div>
<p>The property <code>name</code> is a string field, so we expect a value passed in from
a ProtoRPC message to be a string. Since (as seen below), <code>name</code> is
required, we also need not worry about the case that the value is <code>None</code>.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">basestring</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s">&#39;Name must be a string.&#39;</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-9'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-9'>#</a>
</div>
<p>We update the key using the <code>name</code>.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="bp">self</span><span class="o">.</span><span class="n">UpdateFromKey</span><span class="p">(</span><span class="n">ndb</span><span class="o">.</span><span class="n">Key</span><span class="p">(</span><span class="n">MyParent</span><span class="p">,</span> <span class="n">value</span><span class="p">))</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-10'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-10'>#</a>
</div>
<p>This <code>EndpointsAliasProperty</code> is used for the property <code>name</code>. It is required,
meaning that a value must always be set if the corresponding field is
contained in a ProtoRPC message schema.</p>
<p>Since no <code>property_type</code> is specified, the default value of
<code>messages.StringField</code> is used.</p>
<p>See <a href="/examples/matching_queries_to_indexes.html">matching_queries_to_indexes</a> for more information on <code>EndpointsAliasProperty</code>.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="nd">@EndpointsAliasProperty</span><span class="p">(</span><span class="n">setter</span><span class="o">=</span><span class="n">NameSet</span><span class="p">,</span> <span class="n">required</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-11'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-11'>#</a>
</div>
<p>First check if the entity has a key.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-12'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-12'>#</a>
</div>
<p>If the entity has a key, return only the <code>string_id</code> since the property is
a string field.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">string_id</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-13'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-13'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre><span class="k">class</span> <span class="nc">MyModel</span><span class="p">(</span><span class="n">EndpointsModel</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-14'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-14'>#</a>
</div>
<p>These values are placeholders to be used when a key is created; the <code>_parent</code>
will be used as the ancestor and the <code>_id</code> as the ID. For example:
<br>&nbsp;&nbsp;&nbsp;<code>ndb.Key(MyParent, _parent, MyModel, _id)</code><br>
Since these values will be set by alias properties which are not set
simultaneously, we need to hold them around until both are present before we
can create a key from them.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">_parent</span> <span class="o">=</span> <span class="bp">None</span>
<span class="n">_id</span> <span class="o">=</span> <span class="bp">None</span>
</pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-15'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-15'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre>
<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></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-16'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-16'>#</a>
</div>
<p>This is a helper method that will set the key on the entity only if both the
parent and ID are present. It will be used by property setters that provide
values for <code>_parent</code> and <code>_id</code>.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">SetKey</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-17'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-17'>#</a>
</div>
<p>Can only set the key if both the parent and the child ID are set.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parent</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span> <span class="ow">and</span> <span class="bp">self</span><span class="o">.</span><span class="n">_id</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
<span class="n">key</span> <span class="o">=</span> <span class="n">ndb</span><span class="o">.</span><span class="n">Key</span><span class="p">(</span><span class="n">MyParent</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parent</span><span class="p">,</span> <span class="n">MyModel</span><span class="p">,</span> <span class="bp">self</span><span class="o">.</span><span class="n">_id</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-18'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-18'>#</a>
</div>
<p>Will set the key and attempt to update the entity if it exists.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="bp">self</span><span class="o">.</span><span class="n">UpdateFromKey</span><span class="p">(</span><span class="n">key</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-19'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-19'>#</a>
</div>
<p>This is a helper method that will set the <code>_parent</code> and <code>_id</code> values using the
entity key, if it exists. It will be used by property getters that retrieve
the current values of <code>_parent</code> and <code>_id</code>.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">SetParts</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-20'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-20'>#</a>
</div>
<p>If there is no key, nothing can be set.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">key</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-21'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-21'>#</a>
</div>
<p>If there are not two tuples in the key <code>pairs</code>, a <code>ValueError</code> will occur.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">parent_pair</span><span class="p">,</span> <span class="n">id_pair</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">key</span><span class="o">.</span><span class="n">pairs</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-22'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-22'>#</a>
</div>
<p>Each pair in key <code>pairs</code> will be a tuple (model kind, value) where model
kind is a string representing the name of the model and value is the
actual string or integer ID that was set.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="bp">self</span><span class="o">.</span><span class="n">_parent</span> <span class="o">=</span> <span class="n">parent_pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="bp">self</span><span class="o">.</span><span class="n">_id</span> <span class="o">=</span> <span class="n">id_pair</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-23'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-23'>#</a>
</div>
<p>This is a setter which will be used by the alias property <code>parent</code>. This
method will be called when <code>_parent</code> is set from a ProtoRPC request.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">ParentSet</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-24'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-24'>#</a>
</div>
<p>The property <code>parent</code> is a string field, so we expect a value passed in
from a ProtoRPC message to be a string. Since (as seen below), <code>parent</code> is
required, we also need not worry about the case that the value is <code>None</code>.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">basestring</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s">&#39;Parent name must be a string.&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-25'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-25'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="bp">self</span><span class="o">.</span><span class="n">_parent</span> <span class="o">=</span> <span class="n">value</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-26'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-26'>#</a>
</div>
<p>After setting the value, we must make sure the parent exists before it can
be used as an ancestor.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="n">ndb</span><span class="o">.</span><span class="n">Key</span><span class="p">(</span><span class="n">MyParent</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span><span class="o">.</span><span class="n">get</span><span class="p">()</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-27'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-27'>#</a>
</div>
<p>If the <code>MyParent</code> key does not correspond to an entity in the datastore,
we return an HTTP 404 Not Found.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">raise</span> <span class="n">endpoints</span><span class="o">.</span><span class="n">NotFoundException</span><span class="p">(</span><span class="s">&#39;Parent </span><span class="si">%s</span><span class="s"> does not exist.&#39;</span> <span class="o">%</span> <span class="n">value</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-28'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-28'>#</a>
</div>
<p>The helper method <code>SetKey</code> is called to set the entity key if the <code>_id</code> has
also been set already.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="bp">self</span><span class="o">.</span><span class="n">SetKey</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-29'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-29'>#</a>
</div>
<p>If the <code>parent</code> property is used in a query method, we want the ancestor
of the query to be the parent key.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="bp">self</span><span class="o">.</span><span class="n">_endpoints_query_info</span><span class="o">.</span><span class="n">ancestor</span> <span class="o">=</span> <span class="n">ndb</span><span class="o">.</span><span class="n">Key</span><span class="p">(</span><span class="n">MyParent</span><span class="p">,</span> <span class="n">value</span><span class="p">)</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-30'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-30'>#</a>
</div>
<p>This <code>EndpointsAliasProperty</code> is used to get and set a parent for our entity
key. It is required, meaning that a value must always be set if the
corresponding field is contained in a ProtoRPC message schema.</p>
<p>Since no <code>property_type</code> is specified, the default value of
<code>messages.StringField</code> is used.</p>
<p>See <a href="/examples/matching_queries_to_indexes.html">matching_queries_to_indexes</a> for more information on <code>EndpointsAliasProperty</code>.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="nd">@EndpointsAliasProperty</span><span class="p">(</span><span class="n">setter</span><span class="o">=</span><span class="n">ParentSet</span><span class="p">,</span> <span class="n">required</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">parent</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-31'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-31'>#</a>
</div>
<p>If <code>_parent</code> has not already been set on the entity, try to set it.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parent</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-32'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-32'>#</a>
</div>
<p>Using the helper method <code>SetParts</code>, <code>_parent</code> will be set if a valid key has
been set on the entity.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="bp">self</span><span class="o">.</span><span class="n">SetParts</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-33'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-33'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_parent</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-34'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-34'>#</a>
</div>
<p>This is a setter which will be used by the alias property <code>id</code>. This
method will be called when <code>_id</code> is set from a ProtoRPC request. This replaces
the helper property <code>id</code> provided by <code>EndpointsModel</code>, but does not use any of
the functionality from that method.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">def</span> <span class="nf">IdSet</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-35'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-35'>#</a>
</div>
<p>The property <code>id</code> is a string field, so we expect a value passed in from a
ProtoRPC message to be a string. Since (as seen below), <code>id</code> is required,
we also need not worry about the case that the value is <code>None</code>.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="nb">basestring</span><span class="p">):</span>
<span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s">&#39;ID must be a string.&#39;</span><span class="p">)</span>
</pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-36'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-36'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="bp">self</span><span class="o">.</span><span class="n">_id</span> <span class="o">=</span> <span class="n">value</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-37'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-37'>#</a>
</div>
<p>The helper method <code>SetKey</code> is called to set the entity key if the <code>_parent</code>
has also been set already.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="bp">self</span><span class="o">.</span><span class="n">SetKey</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-38'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-38'>#</a>
</div>
<p>This <code>EndpointsAliasProperty</code> is used to get and set an <code>id</code> value for our
entity key. It is required, meaning that a value must always be set if the
corresponding field is contained in a ProtoRPC message schema.</p>
<p>Since no <code>property_type</code> is specified, the default value of
<code>messages.StringField</code> is used.</p>
<p>See <a href="/examples/matching_queries_to_indexes.html">matching_queries_to_indexes</a> for more information on <code>EndpointsAliasProperty</code>.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="nd">@EndpointsAliasProperty</span><span class="p">(</span><span class="n">setter</span><span class="o">=</span><span class="n">IdSet</span><span class="p">,</span> <span class="n">required</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">id</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-39'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-39'>#</a>
</div>
<p>If <code>_id</code> has not already been set on the entity, try to set it.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">_id</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-40'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-40'>#</a>
</div>
<p>Using the helper method <code>SetParts</code>, <code>_id</code> will be set if a valid key has
been set on the entity.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="bp">self</span><span class="o">.</span><span class="n">SetParts</span><span class="p">()</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-41'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-41'>#</a>
</div>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_id</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></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-42'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-42'>#</a>
</div>
<p>This method is not defined in any of the previous examples; it allows a
parent entity to be inserted so that it can be used as an ancestor. Since
the ProtoRPC message schema for <code>MyParent</code> is a single field <code>name</code>, this will
be all that is contained in the request and the response.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="nd">@MyParent.method</span><span class="p">(</span><span class="n">path</span><span class="o">=</span><span class="s">&#39;myparent&#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;myparent.insert&#39;</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">MyParentInsert</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">my_parent</span><span class="p">):</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-43'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-43'>#</a>
</div>
<p>Though we don't actively change the model passed in, the value of <code>updated</code>
is set to the current time. No check is performed to see if the <code>MyParent</code>
entity already exists, since the values other than the <code>name</code> (set in the
key) are not relevant.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="n">my_parent</span><span class="o">.</span><span class="n">put</span><span class="p">()</span>
<span class="k">return</span> <span class="n">my_parent</span></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-44'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-44'>#</a>
</div>
<p>Since we require <code>MyModel</code> instances also have a <code>MyParent</code> ancestor, we include
<code>parent</code> in the request path by setting <code>path='mymodel/{parent}'</code>. Since <code>id</code>
is also required, an <code>id</code> must be included in the request body or it will be
rejected by ProtoRPC before this method is called.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="nd">@MyModel.method</span><span class="p">(</span><span class="n">path</span><span class="o">=</span><span class="s">&#39;mymodel/{parent}&#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></pre></div>
</div>
</div>
<div class='clearall'></div>
<div class='section' id='section-45'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-45'>#</a>
</div>
<p>If the entity already exists (as evidenced by <code>from_datastore</code> equal to
<code>True</code>), an HTTP 400 Bad Request is returned. Since both <code>parent</code> and <code>id</code>
are required fields, both <code>_parent</code> and <code>_id</code> will be set on the entity and
<code>MyModel.SetKey</code> must have been called.</p>
<p>Checking in this fashion is not truly safe against duplicates. To do this,
a datastore transaction would be necessary.</p>
</div>
<div class='code'>
<div class="highlight"><pre> <span class="k">if</span> <span class="n">my_model</span><span class="o">.</span><span class="n">from_datastore</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">endpoints</span><span class="o">.</span><span class="n">BadRequestException</span><span class="p">(</span>
<span class="s">&#39;MyModel </span><span class="si">%s</span><span class="s"> with parent </span><span class="si">%s</span><span class="s"> already exists.&#39;</span> <span class="o">%</span>
<span class="p">(</span><span class="n">my_model</span><span class="o">.</span><span class="n">id</span><span class="p">,</span> <span class="n">my_model</span><span class="o">.</span><span class="n">parent</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-46'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-46'>#</a>
</div>
<p>To make sure queries have a specified ancestor, we use the alias property
<code>parent</code> which we defined on <code>MyModel</code> and specify <code>query_fields</code> equal to
<code>('parent',)</code>. To specify the parent in the query, it is included in the path
as it was in <code>MyModelInsert</code>. So no query parameters will be required, simply
a request to
<br>&nbsp;&nbsp;&nbsp;<code>.../mymodels/someparent</code><br>
where <code>...</code> is the full path to the API.</p>
</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;parent&#39;</span><span class="p">,),</span>
<span class="n">path</span><span class="o">=</span><span class="s">&#39;mymodels/{parent}&#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-47'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-47'>#</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-48'>
<div class='docs'>
<div class='octowrap'>
<a class='octothorpe' href='#section-48'>#</a>
</div>
<p>That is all for now. More examples to come. Stay tuned.
Head back to the <a href="/">main page</a> if you like.</p>
</div>
</div>
<div class='clearall'></div>
</div>
</body>