Ticket #307 (closed enhancement: fixed)

Opened 20 months ago

Last modified 15 months ago

Provide 'key' attribute for GAE models

Reported by: thijs Owned by:
Priority: critical Milestone: 0.4
Component: Adapter Version: 0.3.1
Keywords: google-app-engine, review Cc: marceloverdijk, fernandoacorreia@…
Fixed in revision: Branch:
Author:

Description (last modified by thijs) (diff)

GAE models get automatically a 'key' assigned by GAE's datastore API.

In a Flex app you might need this key to update records. Currently that key is not send to the Flex client because it's a method on the model class. It should become a attribute called 'key' containing the available properties etc.

Use case:

def getCurrentUser():
   u = GqlQuery("select * from AppUser where googleU = :gu", gu=users.get_current_user()).get()
   if u == None:
      u =  Models.AppUser( googleU = users.get_current_user())
      u.put()

  #setting the id this way doesn't work either....
  #u.id = u.key().id()
  return u

MailingList references:

Attachments

gae-db-key-attr-307.diff Download (1.6 KB) - added by nick 20 months ago.
Patch to include the _key attribute when encoding Model/Expando objects
facorreia-ticket-307.patch Download (1.8 KB) - added by facorreia 19 months ago.
alternative patch proposed
facorreia-ticket-307-with-test.patch Download (4.7 KB) - added by facorreia 19 months ago.
alternate patch with updated test

Change History

  Changed 20 months ago by thijs

  • description modified (diff)

  Changed 20 months ago by thijs

  • component changed from Encoder to Adapters

  Changed 20 months ago by marceloverdijk

vote: +1

  Changed 20 months ago by nick

A possible work around would be to return the key as a separate argument:

def getCurrentUser():
    u = GqlQuery("select * from AppUser where googleU = :gu", gu=users.get_current_user()).get()

    if u == None:
        u =  Models.AppUser(googleU = users.get_current_user())
        u.put()

  return u.key(), u

  Changed 20 months ago by nick

  • status changed from new to accepted
  • version 0.3.1 deleted
  • milestone 0.5 deleted

According to  Google App Engine Docs:

The Python model API ignores all attributes on a Model or Expando that begin with an underscore (_). Your application can use these attributes to associate data with the model objects that is not saved to the datastore.

This means that we can encode the key to an attribute _key (or similar) without interfering with the Datastore stuff.

Changed 20 months ago by nick

Patch to include the _key attribute when encoding Model/Expando objects

  Changed 20 months ago by thijs

  • description modified (diff)

  Changed 20 months ago by thijs

  • version set to 0.3.1
  • type changed from defect to enhancement

  Changed 19 months ago by thijs

  • priority changed from major to critical
  • milestone set to 0.4

  Changed 19 months ago by thijs

  • cc marceloverdijk@… added
  • keywords google app engine added

  Changed 19 months ago by thijs

  • cc marceloverdijk added; marceloverdijk@… removed

follow-up: ↓ 12   Changed 19 months ago by facorreia

  • cc fernandoacorreia@… added

This feature seems very important to me as well. The key can be sent to the client and later used to update or delete the object.

I am proposing an alternative patch with the following modifications:

* The key is returned as an obfuscated string, and not as an integer. This way it is safer to use in a URL and very easy to use back in the server. The Key constructor will accept it, and db.get also does: existing_project = Project.get(project._key)

* The name of the property is _key instead of _pyamf_key. As stated elsewhere, PyAMF has very little to do with this key. It is a GAE model concern.

* I removed some duplication from the code.

There is a working project using this patch:

 http://github.com/fernandoacorreia/flex-and-python-test/tree/25770d9289ba2410668f00310d57ea51a0b6b97c

 http://fernandoacorreia.wordpress.com/2008/07/19/flex-client-updating-objects-in-google-app-engine/

Changed 19 months ago by facorreia

alternative patch proposed

in reply to: ↑ 11   Changed 19 months ago by thijs

  • keywords engine, review added; engine removed
  • status changed from accepted to assigned

Replying to facorreia:

Thanks for the patch facorreia. I'm assigning the ticket to nick for review, but I'm sure he's going to ask about unit tests. Any chance you can supply those as well?

  Changed 19 months ago by facorreia

thijs: This is a fair request. I will try to provide a test fixture, although I am not familiar with PyAMF or Python unit tests.

Changed 19 months ago by facorreia

alternate patch with updated test

  Changed 19 months ago by facorreia

I have updated the test case to reflect the new _key property. Notes:

1. The test is passing on my machine. I noticed that the order of some properties changed from the previous test string. I wonder if the order will be the same in all machines or if it can be random.

2. I don't know the AMF protocol, so I don't know for sure that the output is valid. What I know is: 2a. The _key string is present in the output. 2b. In my sample application the output can be correctly deserialized by Flex.

3. The test doesn't seem to deal with actually persisted objects, so I the key is probably empty.

I am just learning about these tools. I hope someone with more knowledge can pick up from here.

  Changed 18 months ago by nick

  • status changed from assigned to accepted

  Changed 18 months ago by nick

  • keywords google-app-engine added; google app engine, review removed

  Changed 18 months ago by nick

Blocked by #348.

  Changed 15 months ago by nick

  • keywords google-app-engine, review added; google-app-engine removed
  • owner nick deleted
  • status changed from accepted to assigned

Ready for review.

All classes that are decoding need to be aliased. If the _key is provided then the object is first loaded from the datastore before the properties contained in the stream are applied.

I have also uploaded the web runner test to a new GAE application available here for testing:  http://pyamf-test.appspot.com/test

follow-up: ↓ 20   Changed 15 months ago by thijs

There are tests failing on py2.3 and  py2.6:

FAIL: test_get_attributes (test_amf3.ClassDefinitionTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/buildbot/Buildslaves/pyamf/amd64-ubuntu-py26/build/pyamf/tests/test_amf3.py", line 300, in test_get_attributes
    self.assertEquals(d, {'bar': 'baz', 'baz': 'gak'})
AssertionError: {'foo': 'bar'} != {'baz': 'gak', 'bar': 'baz'}

in reply to: ↑ 19   Changed 15 months ago by thijs

Replying to thijs:

There are tests failing on py2.3 and  py2.6: {{{ FAIL: test_get_attributes (test_amf3.ClassDefinitionTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/buildbot/Buildslaves/pyamf/amd64-ubuntu-py26/build/pyamf/tests/test_amf3.py", line 300, in test_get_attributes self.assertEquals(d, {'bar': 'baz', 'baz': 'gak'}) AssertionError: {'foo': 'bar'} != {'baz': 'gak', 'bar': 'baz'} }}}

Oops, that was the wrong branch, no tests failing here.

  Changed 15 months ago by nick

  • status changed from assigned to closed
  • resolution set to fixed

Merged in r1761.

Note: See TracTickets for help on using tickets.