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.
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:
> 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
> > 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.
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 -