Reputation: 1185
[Added Solution at the end of question]
How to to get Property Types of a NDB Model in GAE Python ?
Example model :
class X(ndb.Model):
prop_1 = ndb.IntegerProperty ("a", indexed=True)
prop_2 = ndb.StringProperty ("b")
prop_3 = ndb.DateTimeProperty ("c", repeated=True)
prop_4 = ndb.DateProperty ("d", repeated=False)
Using GAE Metadata API did not help.
I can get list of all properties of model X
using get_properties_of_kind(kind).
But get_representations_of_kind(kind) would not help me get the property types as it has the same property representation values for more than one property type ( like DateTime
and Date
both have INT64
).
ATTEMPT 1
y = globals()["X"] # IF I GET THE MODEL NAME AS STRING; ELSE y = X.
logging.info (y)
logging.info (vars(y))
for item in vars(y):
if (item[0]!="_"): # ASSUMING ALL INTERNAL KEY NAMES START WITH "_".
logging.info ("item=["+item+"] ")
logging.info ("vars(y)[item]=["+repr (vars(y)[item])+"] ")
OUTPUT
2015-03-02 00:08:43.166 +0530 I X<prop_1=IntegerProperty('a'), prop_2=StringProperty('b'), prop_3=DateTimeProperty('c', repeated=True)>
2015-03-02 00:08:43.171 +0530 I {'__module__': '__main__', 'prop_1': IntegerProperty('a'), 'prop_2': StringProperty('b'), 'prop_3': DateTimeProperty('c', repeated=True), '_properties': {'a': IntegerProperty('a'), 'c': DateTimeProperty('c', repeated=True), 'b': StringProperty('b')}, '_has_repeated': True, '__doc__': None}
2015-03-02 00:08:43.186 +0530 I item=[prop_1]
2015-03-02 00:08:43.191 +0530 I vars(y)[item]=[IntegerProperty('a')]
2015-03-02 00:08:43.195 +0530 I item=[prop_2]
2015-03-02 00:08:43.200 +0530 I vars(y)[item]=[StringProperty('b')]
2015-03-02 00:08:43.204 +0530 I item=[prop_3]
2015-03-02 00:08:43.209 +0530 I vars(y)[item]=[DateTimeProperty('c', repeated=True)]
Using this approach, I would get the Property Types of a Model as String ( like, DateTimeProperty('c', repeated=True)
). I would have to extract the Property Type ( DateTimeProperty
) using regex.
Is this the correct ( and the best ) way to do it ?
SOLUTION
Based on answers by @Greg and @Alex Martelli, I was able to come up with a solution :
obj = globals ()["X"]
for item in obj._properties:
logging.info ("b item=["+item+"] ")
# This gave the short names of properties : "a", "b", "c", ..
logging.info ("b needed part = ["+obj._properties[item].__class__.__name__+"] ")
# This gave the property type class : "IntegerProperty", "StringProperty", "DateTimeProperty", ..
for item in obj.__dict__:
if (item[0]!="_"):
logging.info ("HB item=["+item+"] ")
# This gave the actual property name : "prop_1", "prop_2", "prop_3", ..
Note that I could not use the GAE Metadata API since it needs at least one entity of the Model to be present, which is not necessary in my case.
In my situation, I need to create the class name from string ( hence the globals().. ).
Only problem, now, is how to correlate actual property names ( like "prop_1" ) to the obtained property types ? Right now, the short names ( like "a" ) map to property types.
Please let me know if I am doing something wrong.
Upvotes: 0
Views: 1181
Reputation: 881675
If any entity of model class X
exists, I would recommend:
from google.appengine.ext.ndb import metadata
props = metadata.get_properties_of_kind('X')
prop_to_type = {}
for p in props:
prop_to_type[p] = type(getattr(X, p))
If no entity of model class X
exists, props
will be the empty list, so you may have to resort to slightly trickier approaches such as
props = X._property
In this case, props
is a dict
, and its values are instances of property classes -- but you can still loop on props
(getting the dict's keys, which are the property names) and use the same type(getattr(...
code as above to get the actual types.
I nevertheless consider this "slightly trickier" because in Python it's generally considered better to avoid accessing names that start with an underscore, when feasible!-)
Upvotes: 3
Reputation: 10360
If you have a model class, then its _properties
attribute will contain the attributes that are datastore-properties. From there, you can access the __name__
of the class and/or any other attributes of the Property.
You don't need to be accessing globals()
or vars()
like you're doing, and there's definitely no need to resort to regex.
Upvotes: 2