<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Swarling Black Mable &#187; appengine</title>
	<atom:link href="http://blainegarrett.com/tag/appengine/feed/" rel="self" type="application/rss+xml" />
	<link>http://blainegarrett.com</link>
	<description>Blaine Garrett's Home on the Web - Art, Programming, Ideas, and more</description>
	<lastBuildDate>Tue, 02 Aug 2011 18:50:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.1</generator>
		<item>
		<title>Appengine: Transaction Safe Reference Properties with Ancestor Queries</title>
		<link>http://blainegarrett.com/2011/08/02/transaction-safe-reference-properties-ancestor-queries/</link>
		<comments>http://blainegarrett.com/2011/08/02/transaction-safe-reference-properties-ancestor-queries/#comments</comments>
		<pubDate>Tue, 02 Aug 2011 15:44:48 +0000</pubDate>
		<dc:creator>blainegarrett</dc:creator>
				<category><![CDATA[Google AppEngine]]></category>
		<category><![CDATA[appengine]]></category>
		<category><![CDATA[entity groups]]></category>
		<category><![CDATA[transactions]]></category>

		<guid isPermaLink="false">http://blainegarrett.com/?p=1022</guid>
		<description><![CDATA[This is a quick article on transactions with &#8220;one to many&#8221; relationship queries within a single by utilizing entity groups and ancestor queries. If you find it helpful, please feel free to link to it and help spread the google juice. Special thanks to co-worker Robert Kluin for helping me figure this out last week. [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://blainegarrett.com/files/2010/01/saupload_google_appengine.png"><img src="http://blainegarrett.com/files/2010/01/saupload_google_appengine.png" alt="" width="250" height="250" class="alignleft size-full wp-image-840" /></a><br />
This is a quick article on transactions with &#8220;one to many&#8221; relationship queries within a single by utilizing entity groups and ancestor queries. If you find it helpful, please feel free to link to it and help spread the google juice. Special thanks to co-worker <a href="http://ezoxsystems.com" target="_new">Robert Kluin</a> for helping me figure this out last week. </p>
<h2>My Problem</h2>
<p>My initial problem was that I was working inside a transaction and needed to fetch all the entities of a one to many relationship. In my case, I designed my data to be in the same entity group, thus I figured it was transaction safe. However, I was getting the error: <b>BadRequestError: Only ancestor queries are allowed inside transactions.</b>.  This had me a bit stumped since I was not actually doing any queries inside of the code. However, Appengine itself was under the hood.</p>
<h2>The Issue</h2>
<p>With a bit of discussion with my coworkers, I traced the problematic query back to the underlying query behind Appengine&#8217;s handy named reference property.<br />
I had a kind (we&#8217;ll call it Hand) that had a one-to-many relationship on a kind (we&#8217;ll call Finger). The issue is that <b>hand.fingers</b> does not run an ancestor query. In my specific case, this did not make sense, since all the <em>fingers</em> were in the same entity group as their parent <em>hand</em>. However, since reference properties do not have to be in the same entity group, the query resembles <b>Finger.all().filter(&#8216;hand =&#8217;, hand)</b> which is obviously not a ancestor query. </p>
<h2>The solution</h2>
<p>The solution is to avoid using the reference property and manually query <b>fingers = Finger.all().ancestor(hand)</b>. This will fetch all of the finger entities that have an ancestor (parent) of hand. Note: that this is not the same as a reference property query and that the links between parent/child entities among an entity group have a different purpose than reference properties even though they often coincidentally have an overlap in the data. This solution leverages this coincidence. </p>
<h2>Example Code</h2>
<p>Note: I didn&#8217;t actually run this specific code. Use at your own risk.</p>
<pre class="brush: python">
from google.appengine.ext import db
from base.datastore.util import transaction

class Hand(db.Model):
    is_right = db.BooleanProperty()
    is_dominant = db.BooleanProperty()

class Finger(db.Model):
	position = db.IntegerProperty(default=0)
	hand = db.ReferenceProperty(Hand, collection_name=&#039;fingers&#039;)

	def trim_nail(self):
		#... do work
		pass

def trim_my_nails(hand):
	@transaction
	def txn(hand):
		#fingers = hand.fingers # NOT TRANSACTION SAFE
		fingers = Finger.all().ancestor(hand) # Transaction safe
		for finger in fingers:
			finger.trim_nail()
		#... do whatever transaction friendly tasks
		return hand
	trimmed_hand = txn(hand)
    return hand
</pre>
<h2>Quick Notes and Pitfalls</h2>
<p>* Transactions only allow ancestor queries<br />
* Ancestor queries only work when the data is in the same entity group<br />
* Given the above, transactions can only query data in the same entity group.<br />
* Ancestor queries are far faster than regular queries because of the way that GAE stores their data for entity groups.<br />
* Entity groups are recommended to only be &#8220;about the size of one user&#8217;s data&#8221; and should not get too big. In the example above, you probably don&#8217;t want &#8220;everyone&#8217;s hands and their fingers&#8221; in the same entity group just to be able to work inside of transactions. Model your workflow better to avoid this.<br />
* If you are on high-replication datastore (HRD), then this works even faster.<br />
* If you have a long chain of parent relationships and the model in the ancestor query is the parent of the parent, you may get more entities back than you expect. The hand/finger example is a bad analogy in this case. However, if you think of Forums with Sub-Forums and you try to get all the posts with the ancestor some forum entity, you might be getting back all the posts of that forum as well as any of its child forums. This is ideal for some situations and is unexpected  behavior for others. </p>
<p>Further Reading</p>
<ul>
<li><a href="http://code.google.com/appengine/docs/python/datastore/queries.html" target="_new">Datastore Indexes and Queries</a> Google App Engine Docs</li>
<li><a href="http://code.google.com/appengine/docs/python/datastore/transactions.html" target="_new">Transactions</a> Google App Engine Docs</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blainegarrett.com/2011/08/02/transaction-safe-reference-properties-ancestor-queries/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Appengine: getCurrentUser() is None but app.yaml login:admin Allows Access?</title>
		<link>http://blainegarrett.com/2010/05/14/appengine-getcurrentuser-is-none-but-app-yaml-loginadmin-allows-access/</link>
		<comments>http://blainegarrett.com/2010/05/14/appengine-getcurrentuser-is-none-but-app-yaml-loginadmin-allows-access/#comments</comments>
		<pubDate>Fri, 14 May 2010 21:20:28 +0000</pubDate>
		<dc:creator>blainegarrett</dc:creator>
				<category><![CDATA[Google AppEngine]]></category>
		<category><![CDATA[app.yaml]]></category>
		<category><![CDATA[appengine]]></category>
		<category><![CDATA[getCurrentUser]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[login]]></category>
		<category><![CDATA[service]]></category>
		<category><![CDATA[user]]></category>

		<guid isPermaLink="false">http://blainegarrett.com/?p=884</guid>
		<description><![CDATA[Today, while working on Google AppEngine code, I discovered a bug in AppEngine, but it just turned out to be a typo. I spent a good few hours googling before tearing things apart and solving the tricky issue. As such, I am sharing my finds to help others&#8217; save some time and stress. Short version [...]]]></description>
			<content:encoded><![CDATA[<p><a rel="attachment wp-att-840" href="http://blainegarrett.com/2010/01/25/appengine-djangogql-ensuring-uniqueness-of-model-type-on-edit/saupload_google_appengine/"><img class="alignleft size-full wp-image-840" src="http://blainegarrett.com/files/2010/01/saupload_google_appengine.png" alt="saupload_google_appengine" width="250" height="250" /></a>Today, while working on Google AppEngine code,  I discovered a bug in AppEngine, but it just turned out to be a typo. I spent a good few hours googling before tearing things apart and solving the tricky issue. As such, I am sharing my finds to help others&#8217; save some time and stress. <strong>Short version is to check your regular expressions in the app.yaml file when adding security to an entire folder.</strong></p>
<p><strong>Here is the skinny: </strong><br />
I was running into an unexpected issue with the AppEngine users service on a folder locked down by app.yaml. I had a folder <strong>/cms/</strong> that I wanted the contents of to only be viewed by admin users to my Google AppEngine project. All pages inside of the directory displayed the email address of the user as well as a log out link. I was using <strong>users.GetCurrentUser() </strong> and <strong>users.create_logout_url</strong> to display this. The folder itself was being locked down at the app.yaml level. Aside from this, there was no other security (@require_admin decorators, etc). After testing, I discovered I was able to return to pages within /cms/ while being logged out via the <strong>users.create_logout_url</strong> link. <strong>users.GetCurrentUser() </strong> was returning None as expected, but I figured I would be redirected to a Google login page. </p>
<p>I figured this might be a bug with the current sdk, but I wasn&#8217;t willing to assume that until I had support. After submitting to the python mailing list with no reply, some googling, I started debugging the app.yaml. In the end I discovered it to be the url matching condition to the app.yaml file &#8211; essentially a logical &#8220;typo&#8221;. For what it is worth, I didn&#8217;t check here first because I am making changes to an existing set of code that already had the app.yaml condition in place. However, if you are in the same boat ever, hopefully this info will help.</p>
<p>So, if you think you have a folder locked down with app.yaml and users are still able to visit the page while logged out, check the url conditions. Examples below:</p>
<p>My app.yaml has</p>
<pre class="brush: python">
#- url: /cms # BAD VERSION - only protects a file named cms in the root, not the cms folder&lt;/del&gt;
- url: /cms.* # GOOD VERSION - protects any url matching the regexp &quot;starts with &#039;/cms&#039; followed by any number of characters (including &#039;/&#039;) &quot;
  script: main.py
  login: admin
  secure: always
</pre>
<p>Hopefully, that helps someone out. I know I wasted lunch break figuring it out. </p>
<p>On the page, I display the value of users.GetCurrentUser() and have a logout link generated by users.create_logout_url(&#8216;/home/&#8217;).<br />
When I click logout, I am redirected to /home/ as expected.</p>
<p>The odd behavior is that I can then go to /cms/ again without having to reauthenticate. The value of users.GetCurrentUser() is None (as expected).<br />
However, I would expect the app.yaml to cause me to be redirected to the Google login screen when trying to revisit logged out.</p>
<p>I have not tested on production yet. Is this correct behavior and/or a known issue on dev sdk?</p>
]]></content:encoded>
			<wfw:commentRss>http://blainegarrett.com/2010/05/14/appengine-getcurrentuser-is-none-but-app-yaml-loginadmin-allows-access/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Appengine Django/GQL &#8211; Ensuring Uniqueness of Model Type on Edit &#8211; Not Equals Filters</title>
		<link>http://blainegarrett.com/2010/01/25/appengine-djangogql-ensuring-uniqueness-of-model-type-on-edit/</link>
		<comments>http://blainegarrett.com/2010/01/25/appengine-djangogql-ensuring-uniqueness-of-model-type-on-edit/#comments</comments>
		<pubDate>Mon, 25 Jan 2010 22:40:33 +0000</pubDate>
		<dc:creator>blainegarrett</dc:creator>
				<category><![CDATA[Google AppEngine]]></category>
		<category><![CDATA[appengine]]></category>
		<category><![CDATA[Django]]></category>
		<category><![CDATA[filter]]></category>
		<category><![CDATA[forms]]></category>
		<category><![CDATA[google]]></category>
		<category><![CDATA[unique]]></category>

		<guid isPermaLink="false">http://blainegarrett.com/?p=837</guid>
		<description><![CDATA[Edit 2009-02-02 - Added note about inequality query complexity. Spoiler &#8211; inequalities are 2 queries under the hood. In my further adventures in Google AppEngine land, I wanted to ensure uniqueness of an email field while still allowing the user to change their email address. Since, Google App Engine&#8217;s BigTable doesn&#8217;t allow you to custom [...]]]></description>
			<content:encoded><![CDATA[<p><a rel="attachment wp-att-840" href="http://blainegarrett.com/2010/01/25/appengine-djangogql-ensuring-uniqueness-of-model-type-on-edit/saupload_google_appengine/"><img class="alignleft size-full wp-image-840" src="http://blainegarrett.com/files/2010/01/saupload_google_appengine.png" alt="saupload_google_appengine" width="250" height="250" /></a></p>
<p><strong>Edit 2009-02-02 -</strong> Added note about inequality query complexity. Spoiler &#8211; inequalities are 2 queries under the hood.</p>
<p>In my further adventures in Google AppEngine land, I wanted to ensure uniqueness of an email field while still allowing the user to change their email address. Since, Google App Engine&#8217;s BigTable doesn&#8217;t allow you to custom define unique indexes, this poses a problem. Instead of relying on database defined indexes, you have to set up your own rules, which is a wee bit tricky for GAE beginners such as me.<br />
<a href="http://squeeville.com/2009/01/30/add-a-unique-constraint-to-google-app-engine/">This can be done in general by overloading the put() method on an entity</a>, but I wanted to be able to handle the errors nicely for the form UI.</p>
<p>The old Django Method:</p>
<pre class="brush: python">
#account = account entity you are editing
email = form.cleaned_data[&#039;email&#039;].lower()
users_with_this_email = User.objects.filter(email=email).exclude(pk=account.pk).count()
if (users_with_this_email &gt; 0):
# do something...
</pre>
<p>The new Google AppEngine Big Table GQL method:</p>
<pre class="brush: python">
#account = account entity you are editing
...
email = form.cleaned_data[&#039;email&#039;].lower()
users_with_this_email = Account.all().filter(&#039;email = &#039; , email).filter(&#039;__key__ != &#039; , account.key()).count(1)
if (users_with_this_email &gt; 0):
# do something...
</pre>
<p>The key here is making sure some OTHER entity does not also have the value for their email field.<br />
In regular Django, an entity will evaluate to its primary key when used in a query and can be filtered on &#8216;pk&#8217; .<br />
GQL, however, the primary key needs to be explicitly fetched via entity.key() and filtered on __key__</p>
<p>A couple other notes:</p>
<ul>
<li>GQL does have an email property. I have not run tests yet to tell if this is case sensitive.</li>
<li><a href="http://gae-java-persistence.blogspot.com/2009/11/case-insensitive-queries.html">GQL does not allow case-insensitive searches like regular Django does</a>. Thus, I am making sure all email addresses are lowercased when inserting and querying against the db. Even if this is not needed for EmailProperties, you will need it for ensuring the uniqueness of other types.</li>
<li>!= filters are actually ran as two queries &#8211; one where the != is replace with a less than inequality filter, and one where it is replaced with a greater than inequality  filter. No word at the moment if this applies to __key__ searches.</li>
<li>A query with a != cannot have inequality filters because of the above rule nor other != filters.</li>
</ul>
<p>Related Links</p>
<ul>
<li><a href="http://squeeville.com/2009/01/30/add-a-unique-constraint-to-google-app-engine/">Add A Unique Constraint to Google App Engine</a> via Squeeville</li>
<li><a href="http://gae-java-persistence.blogspot.com/2009/11/case-insensitive-queries.html">Case Insensitive Queries</a> via GAE Java Persistence</li>
<li><a href="http://code.google.com/appengine/docs/python/datastore/typesandpropertyclasses.html">Appengine Types and Properties</a> via Google Code</li>
<li><a href="http://code.google.com/appengine/docs/python/datastore/queriesandindexes.html">Queries and Index </a>via Google Code &#8211; discussion on inequalities and != filters</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blainegarrett.com/2010/01/25/appengine-djangogql-ensuring-uniqueness-of-model-type-on-edit/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

