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]

Reply via email to