gsinha gsinha - 1 year ago 72
Python Question

How to to get Property Types of a NDB Model in GAE Python

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

Answer Source

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.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download