Hi, In GAE it's possibe to supply a "key_name" when you insert an entity. This is a string that you can then use as an id to efficiently fetch an entity from db. ( https://developers.google.com/appengine/docs/python/datastore/entities#Python_Kinds_and_identifiers )
I would like to be able to do this using web2py. I could also choose to use the GAE API directly to do this but then a could not make use thing like calculated Fields etc in my web2py tables. I made the following modification to the GoogleDatastoreAdapter insert() function: def insert(self,table,fields): dfields=dict((f.name,self.represent(v,f.type)) for f,v in fields) # table._db['_lastsql'] = self._insert(table,fields) # Field name 'gae_key_name' can be used insert using key_name for both DB and NDB. keyname = None *if 'gae_key_name' in dfields: keyname = dfields['gae_key_name'] if self.use_ndb: dfields['id'] = dfields.pop('gae_key_name') else: dfields['key_name'] = dfields.pop('gae_key_name')* tmp = table._tableobj(**dfields) tmp.put() key = tmp.key if self.use_ndb else tmp.key() rid = Reference(key.id()) (rid._table, rid._record, rid._gaekey) = (table, None, key) return rid Now one can insert using a field name 'gae_key_name'. DB and NDB expect different parameter names for the model constructors to supply a key_name. 'key_name vs 'id''. Now the only problem is that _listify() in Table required that all fields are defined in the Table. We can now choose to define a Field "gae_key_name" in every Table that we want to use this feature for. Another option is to modify the _listify function a bit to accomodate this: def _listify(self,fields,update=False): new_fields = {} # format: new_fields[name] = (field,value) # store all fields passed as input in new_fields # 'gae_key_name' is GAE specific and should not be defined in the table. for name in fields: if not name in self.fields: *if name not in ['id', 'gae_key_name']: raise SyntaxError( 'Field %s does not belong to the table' % name) if name == 'gae_key_name': # Create stub Field for 'gae_key_name' so it can be included # without being defined in the model. field = Field('gae_key_name', 'string') new_fields['gae_key_name'] = field, fields['gae_key_name']* else: field = self[name] value = fields[name] if field.filter_in: value = field.filter_in(value) new_fields[name] = (field,value) The last option feels a bit hacky but removes the requirement to define a Field 'gae_key_name' in every Table. What to you think? I attached a patch that includes both changes. Regards, Quint -- Resources: - http://web2py.com - http://web2py.com/book (Documentation) - http://github.com/web2py/web2py (Source code) - https://code.google.com/p/web2py/issues/list (Report Issues) --- You received this message because you are subscribed to the Google Groups "web2py-users" group. To unsubscribe from this group and stop receiving emails from it, send an email to web2py+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/groups/opt_out.
Index: E:/repositories/Mercurial/web2py/gluon/dal.py =================================================================== --- E:/repositories/Mercurial/web2py/gluon/dal.py (revision 5706:f691e2676f64) +++ E:/repositories/Mercurial/web2py/gluon/dal.py (revision 5706+:f691e2676f64+) @@ -5300,6 +5300,15 @@ def insert(self,table,fields): dfields=dict((f.name,self.represent(v,f.type)) for f,v in fields) # table._db['_lastsql'] = self._insert(table,fields) + # Field name 'gae_key_name' can be used insert using key_name for both DB and NDB. + keyname = None + if 'gae_key_name' in dfields: + keyname = dfields['gae_key_name'] + if self.use_ndb: + dfields['id'] = dfields.pop('gae_key_name') + else: + dfields['key_name'] = dfields.pop('gae_key_name') + tmp = table._tableobj(**dfields) tmp.put() key = tmp.key if self.use_ndb else tmp.key() @@ -9035,11 +9044,17 @@ new_fields = {} # format: new_fields[name] = (field,value) # store all fields passed as input in new_fields + # 'gae_key_name' is GAE specific and should not be defined in the table. for name in fields: if not name in self.fields: - if name != 'id': + if name not in ['id', 'gae_key_name']: raise SyntaxError( 'Field %s does not belong to the table' % name) + if name == 'gae_key_name': + # Create stub Field for 'gae_key_name' so it can be included + # without being defined in the model. + field = Field('gae_key_name', 'string') + new_fields['gae_key_name'] = field, fields['gae_key_name'] else: field = self[name] value = fields[name]