如何在 GAE Python 中获取 属性 NDB 模型的类型

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

[在问题末尾添加解决方案]

如何在 GAE Python 中获取 属性 NDB 模型的类型?

示例模型:

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)

使用 GAE Metadata API 没有帮助。

我可以使用 get_properties_of_kind(kind) 获取模型 X 的所有属性列表。

但是 get_representations_of_kind(kind) 不会帮助我获得 属性 类型,因为它对多个 属性 类型具有相同的 属性 表示值(例如 DateTimeDate 都有 INT64 )。

尝试 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])+"] ")

输出

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)]

使用这种方法,我会将模型的 属性 类型作为字符串(例如 DateTimeProperty('c', repeated=True) )。我将不得不使用正则表达式提取 属性 类型( DateTimeProperty )。

这是正确的(也是最好的)方法吗?

解决方案
根据@Greg 和@Alex Martelli 的回答,我想出了一个解决方案:

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", ..  

注意 我不能使用 GAE Metadata API 因为它需要至少一个模型实体存在,这对我来说不是必需的。
在我的情况下,我需要从字符串创建 class 名称(因此是 globals().. )。

现在唯一的问题是如何将实际的 属性 名称(如 "prop_1" )与获得的 属性 类型相关联?现在,短名称(如 "a" )映射到 属性 类型。

如果我做错了什么,请告诉我。

如果您有一个模型 class,那么它的 _properties 属性将包含数据存储属性。从那里,您可以访问 class 的 __name__ and/or 属性 的任何其他属性。

您不需要像现在这样访问 globals()vars(),而且绝对没有必要求助于正则表达式。

如果模型 class X 的任何实体存在,我建议:

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))

如果不存在模型 class X 的实体,props 将是空列表,因此您可能不得不求助于稍微棘手的方法,例如

props = X._property

在这种情况下,props 是一个 dict,它的值是 属性 classes 的 个实例 - - 但你仍然可以在 props 上循环(获取字典的键,即 属性 名称)并使用与上面相同的 type(getattr(... 代码来获取实际类型。

我仍然考虑这个 "slightly trickier" 因为在 Python 中,通常认为在可行的情况下最好避免访问以下划线开头的名称!-)