7

我正在 GAE 和 Python 2.7 运行时编写我的第一个 RESTful Web 服务;我已经开始使用 Guido 闪亮的新 ndb API。

但是,如果没有原始 db API 的隐式反向引用功能,我不确定如何解决特定情况。如果用户代理请求特定资源并且这些资源被移除 1 度:

主机/api/种类/id?depth=2

鉴于相关实体的类型在开发时未知,从一对多关系中的“一个”中发现相关实体集合的最佳方法是什么?

  • 由于后一个限制,我无法使用先前 SO查询中描述的替换查询。我的模型在运行时是可定义的(因此不是硬编码的)这一事实阻止我使用查询来过滤匹配键的属性。

  • 由于数据存储限制阻止我过滤没有指定种类的属性,祖先和其他无种类查询也被排除在外。

到目前为止,我唯一的想法(除了恢复到 db api)是使用跨组事务在“one”上写入我自己的引用,或者通过更新 ndb.StringProperty(repeat=True) 包含引入新类型的实体时的所有相关类型,或者每次将相关的“许多”实体写入数据存储时,只需在“一个”ndb.KeyProperty(repeat=True) 上维护一个键列表。

我希望比我更有经验的人可以提出更好的方法。

鉴于 jmort253 的建议,我将尝试用一个改编自文档的具体示例来扩充我的问题:

class Contact(ndb.Expando):
    """ The One """

    # basic info
    name = ndb.StringProperty()
    birth_day = ndb.DateProperty()

    # If I were using db, a collection called 'phone_numbers' would be implicitly 
    # created here.  I could use this property to retrieve related phone numbers 
    # when this entity was queried.  Since NDB lacks this feature, the service 
    # will neither have a reference to query nor the means to know the 
    # relationship exists in the first place since it cannot be hard-coded.  The
    # data model is extensible and user-defined at runtime; most relationships
    # will be described only in the data, and must be discoverable by the server.
    # In this case, when Contact is queried, I need a way to retrieve the
    # collection of phone numbers.

    # Company info.
    company_title = ndb.StringProperty()
    company_name = ndb.StringProperty()
    company_description = ndb.StringProperty()
    company_address = ndb.PostalAddressProperty()

class PhoneNumber(ndb.Expando):
    """ The Many """

    # no collection_name='phone_numbers' equivalent exists for the key property
    contact = ndb.KeyProperty(kind='Contact')
    number = ndb.PhoneNumberProperty()
4

2 回答 2

8

有趣的问题!所以基本上你想看看 Contact 类,看看是否有其他模型类有一个 KeyProperty 引用它;在这个例子中电话号码(但可能有很多)。

我认为解决方案是要求您的用户在创建 PhoneNumber 类时明确添加此链接。

您可以通过为用户提供一个处理此问题的 KeyProperty 子类来简化用户的操作;例如

class LinkedKeyProperty(ndb.KeyProperty):
    def _fix_up(self, cls, code_name):
        super(LinkedKeyProperty, self)._fix_up(cls, code_name)
        modelclass = ndb.Model._kind_map[self._kind]
        collection_name = '%s_ref_%s_to_%s' % (cls.__name__,
                                               code_name,
                                               modelclass.__name__)
        setattr(modelclass, collection_name, (cls, self))

究竟如何选择集合的名称和存储的价值取决于您;只需在此处放置一些内容,以使您可以轻松地按照链接返回。该示例将在 Contact 上创建一个新属性:

Contact.PhoneNumber_ref_contact_to_Contact == (PhoneNumber, PhoneNumber.contact)

[编辑以使代码正常工作并添加示例。:-)]

于 2012-05-24T14:04:00.273 回答
2

听起来像是ndb.StructuredProperty.

于 2012-05-24T11:49:39.070 回答