Hi Tim,

An ID is part of the key. When you call db.allocate_ids, you pass in a
datastore key which specifies the kind name and parent (if any) for which to
allocate the ID range. The IDs returned can then be used to create keys as
you normally would from an ID:

start_range, end_range = db.allocate_ids(my_key, 10); # my_key is any
datastore key
for i in range(start_range, end_range):
  a_new_key = db.Key.from_path(my_key.kind(), i, parent=my_key.parent())
  # Do something with a_new_key.

-Nick Johnson

On Thu, Jul 28, 2011 at 12:49 AM, Tim <[email protected]> wrote:

>
> This is a bit of an advanced question for the experts with regards to Keys,
> IDs, Models and the db.allocate_ids() functionality - those who can answer
> it won't need much more explanation, so apologies if it doesn't make much
> sense to everyone else (but you may want to file it away in case you ever
> need to do the same).
>
> My one-page-webapp uses a datastore framework that gets a bit distraught
> when it has create new items and allocate temporary IDs which will later get
> replaced with "true" IDs from the datastore (I've been using the actual Key
> strings as ids), so I thought I'd have a look at pre-allocating IDs.
>
> In the absence of cookbook examples, I've concluded
>
>    - I can pre-allocate a range of IDs for a given class using
>    db.allocate_ids(), but as individual keys encode the id and the parent
>    instance (if any) then I can't convert these pre-allocated IDs into
>    pre-allocated Keys if I may be using parent objects.
>
> False - see above.

>
>    - So I should change the client to use IDs (or maybe "type+id" tuples),
>    and have queries to the GAE server return items with 'obj.key().id()' 
> rather
>    than 'str(obj.key())'
>
> Switching to passing IDs in generated pages is a good idea in general, but
has absolutely no impact on the functionality.


>
>    - The client can be given a range of pre-allocated IDs that it can
>    safely assign to new records as it creates them, knowing they won't change
>    when the item is created in the datastore
>
> Correct.

>
>    - For updating/deleting items on GAE, I'll replace calls to
>    "db.get(key)" (where the key came from the client, and yes I then check the
>    object is valid etc before I proceed) with "MyModel.get_by_id(ids)" (I know
>    the types of objects by this stage so it's not like I'm doing a
>    heterogeneous fetch)
>
> This is what you should do if you're passing IDs instead of complete keys,
but as noted above, has no impact on functionality.

>
>    - I'll still store references to other objects by db.ReferenceProperty
>    type (ie key) rather than simple id as it makes migration of data easier 
> (ie
>    use of IDs rather than Keys is a client layer convenience only)
>
> Correct.

>
>    - I'll implement a new model base class for all db.Model derived
>    classes, that defines a new optional "id" parameter and constructs the
>    correct key (my python knowledge of the constructs is bit green, so I think
>    this does what I expect - kind() is a reserved but undocumented instance
>    method that looks safer than using __name__ by looking at the SDK source)
>
> You can do this if you want, but it's purely convenience. Don't override
the constructor, create a class method instead. The constructor is used to
reconstitute existing entities from the datastore in addition to creating
new ones, so overriding it correctly is difficult.

The kind() method is a class method, not an instance method, and is
documented:
http://code.google.com/appengine/docs/python/datastore/modelclass.html#Model_kind



> class BaseModel(db.Model):
>     def __init__(self, id=None, parent=None, **args):
>         if id != None:
>             args["key"] = db.Key.from_path(self.kind(), id, parent=parent)
>         db.Model.__init__(self, parent=parent, **args)
>
> The db.Model ctor docs say that "key" can't be used with parent or
> key_name, looking at the SDK source implies the last line of the above
> should be fine, but would I do better to omit the "parent=parent" parameter
> and rely on the fact that, if needed, the parent object is looked up form
> the key?
>

They can't be used together because a fully qualified key includes the
parent and key name, and thus there's no need to specify them separately.


>
>    - I can then make instances as before 'obj = MyModel(someproperty=97,
>    another="Hello world")' but I now have a special optional "id" property for
>    construction. I haven't changed parent or property semantics or the like.
>
> Does the above look reasonable enough? I take it the efficiency is pretty
> much the same (ie there's no great added overhead such as extra database
> calls introduced by any of the above) but as I'm no great python expert, and
> the calls above are documented but not always explained, does the above look
> reasonable enough or am I laying myself open to a world of pain to come?
>
> Cheers
>
> --
> Tim
>
>  --
> You received this message because you are subscribed to the Google Groups
> "Google App Engine" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/google-appengine/-/EICnNig9mKkJ.
> To post to this group, send email to [email protected].
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/google-appengine?hl=en.
>



-- 
Nick Johnson, Developer Programs Engineer, App Engine

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-appengine?hl=en.

Reply via email to