Ticket #307 (closed enhancement: fixed)

Opened 6 months ago

Last modified 10 days ago

Provide 'key' attribute for GAE models

Reported by: thijs Owned by:
Priority: critical Milestone: 0.4
Component: Adapters Version: 0.3.1
Keywords: google-app-engine, review Cc: marceloverdijk, fernandoacorreia@…

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 (1.6 KB) - added by nick 5 months ago.
Patch to include the _key attribute when encoding Model/Expando objects
facorreia-ticket-307.patch (1.8 KB) - added by facorreia 5 months ago.
alternative patch proposed
facorreia-ticket-307-with-test.patch (4.7 KB) - added by facorreia 4 months ago.
alternate patch with updated test

Change History

  Changed 6 months ago by thijs

  • description modified (diff)

  Changed 6 months ago by thijs

  • component changed from Encoder to Adapters

  Changed 6 months ago by marceloverdijk

vote: +1

  Changed 6 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 5 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 5 months ago by nick

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

  Changed 5 months ago by thijs

  • description modified (diff)

  Changed 5 months ago by thijs

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

  Changed 5 months ago by thijs

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

  Changed 5 months ago by thijs

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

  Changed 5 months ago by thijs

  • cc marceloverdijk added; marceloverdijk@… removed

follow-up: ↓ 12   Changed 5 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 5 months ago by facorreia

alternative patch proposed

in reply to: ↑ 11   Changed 4 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 4 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 4 months ago by facorreia

alternate patch with updated test

  Changed 4 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 3 months ago by nick

  • status changed from assigned to accepted

  Changed 3 months ago by nick

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

  Changed 3 months ago by nick

Blocked by #348.

  Changed 13 days 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 11 days 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 11 days 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 10 days ago by nick

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

Merged in r1761.

Note: See TracTickets for help on using tickets.