ReferenceProperty - id access without fetching the entity

105 views
Skip to first unread message

Andy Freeman

unread,
Sep 29, 2008, 9:23:48 PM9/29/08
to Google App Engine
Is there an approved way to copy a ReferenceProperty from one entity
to another without fetching the referred to entity from the datastore?

In other words,

class C(db.Model):
...

class A(db.Model):
C = db.ReferenceProperty(reference_class=C)

class B(db.Model):
C = db.ReferenceProperty(reference_class=C)

a = {some query}
b = B()
# I would like to do the next assignment without retrieving the
relevant entity
# from the data store.
b.C = a.C

Yes, I know that a._C.id() can be used to read the id, but that
doesn't seem to be part of the documented interface.

Marzia Niccolai

unread,
Sep 30, 2008, 1:40:37 PM9/30/08
to google-a...@googlegroups.com
Hi,

The method that you are using currently works, but there is no guarantee that it will continue to work in the future - by which I mean that the current API design only specifies that ReferenceProperty is fetched from the datastore when referenced.

We've had requests that there be a way to expose only the key of the reference, and not the actual entity, and I think this is a valid feature request.  I don't believe it's filed in the tracker, so you should do that, and those interested in this feature should star the issue.

-Marzia

Rafe

unread,
Oct 2, 2008, 6:02:01 PM10/2/08
to Google App Engine
Mazia is correct, there is no guarantee that this will work. In
fact, it is very likely it will not work in the future. We may in the
future implement lazy loading so that you can access the key directly
without loading the entity (a.C.key()) however, for now, this is
guaranteed to work:

A.C.get_value_for_datastore(a).key()

Rafe

unread,
Oct 2, 2008, 6:22:34 PM10/2/08
to Google App Engine
Correction on this post :(

A.C.get_value_for_datastore(a)

It is not necessary to call 'key()' because the object that gets
returns IS the key.

On Oct 2, 3:02 pm, Rafe <slobberch...@gmail.com> wrote:
>   Mazia is correct, there is no guarantee that this will work.  In
> fact, it is very likely it will not work in the future.  We may in the
> future implement lazy loading so that you can access the key directly
> without loading the entity (a.C.key()) however, for now, this is
> guaranteed to work:
>
>   A.C.get_value_for_datastore(a).key()
>
> On Sep 29, 6:23 pm, Andy Freeman <ana...@earthlink.net> wrote:
>
> > Is there an approved way to copy aReferencePropertyfrom one entity

Andy Freeman

unread,
Oct 12, 2008, 6:43:03 PM10/12/08
to Google App Engine
That's too much typing so I defined the following.

# AddKeyReference is a __metaclass__ for db.Model subclasses that adds
# a property named x_key for every db.ReferenceProperty named x in the
# classes (and their subclasses). x_key's value is x's db.Key, but is
# produced without fetching x's model instance from the datastore.
# x_key can also be set using None, a string, or a db.Key.
class AddKeyReference(db.Model.__metaclass__):
def __init__(cls, namestring, bases, dct):
super(AddKeyReference, cls).__init__(namestring, bases, dct)
for (k,v,) in dct.iteritems():
if isinstance(v, db.ReferenceProperty):
key_name = k + '_key'
if hasattr(cls, key_name):
raise db.DuplicatePropertyError(
'%s can not be redefined for ReferenceProperty
key' %
(key_name,))
# save key_name, v's current value - all iterations
use the same variables
def set(instance, value, key_name=key_name, r_p=v):
if isinstance(value, basestring):
value = db.Key(value)
if not ((None is value) or isinstance(value,
db.Key)):
raise db.BadKeyError('%s can not be %s' %
(key_name, str(value),))
r_p.__set__(instance, value)
setattr(cls, key_name,
property(lambda instance, r_p=v:

r_p.get_value_for_datastore(instance),
set))

# example
class Test(db.Model):
__metaclass__ = AddKeyReference
xx = db.SelfReferenceProperty()

test = Test()
test.put()
assert None is test.xx
assert None is test.xx_key

test.xx = test
assert test.xx_key == test.key()

test.xx = None
assert None is test.xx_key

test.xx_key = test.key()
# at this point test.xx.xx will cause a datastore fetch





On Oct 2, 3:02 pm, Rafe <slobberch...@gmail.com> wrote:
>   Mazia is correct, there is no guarantee that this will work.  In
> fact, it is very likely it will not work in the future.  We may in the
> future implement lazy loading so that you can access the key directly
> without loading the entity (a.C.key()) however, for now, this is
> guaranteed to work:
>
>   A.C.get_value_for_datastore(a)
>
> On Sep 29, 6:23 pm, Andy Freeman <ana...@earthlink.net> wrote:
>
>
>
> > Is there an approved way to copy a ReferenceProperty from one entity
> > to another without fetching the referred to entity from the datastore?
>
> > In other words,
>
> > class C(db.Model):
> >     ...
>
> > class A(db.Model):
> >     C = db.ReferenceProperty(reference_class=C)
>
> > class B(db.Model):
> >     C = db.ReferenceProperty(reference_class=C)
>
> > a = {some query}
> > b = B()
> > # I would like to do the next assignment without retrieving the
> > relevant entity
> > # from the data store.
> > b.C = a.C
>
> > Yes, I know that a._C.id() can be used to read the id, but that
> > doesn't seem to be part of the documented interface.- Hide quoted text -
>
> - Show quoted text -
Reply all
Reply to author
Forward
0 new messages