跟踪 NDB 中未知种类的反向引用 [英] Following backreferences of unknown kinds in NDB

查看:22
本文介绍了跟踪 NDB 中未知种类的反向引用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm in the process of writing my first RESTful web service atop GAE and the Python 2.7 runtime; I've started out using Guido's shiny new ndb API.

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

However, I'm unsure how to solve a particular case without the implicit back-reference feature of the original db API. If the user-agent requests a particular resource and those resources 1 degree removed:

host/api/kind/id?depth=2

host/api/kind/id?depth=2

考虑到相关实体的类型在开发时未知,从一对多关系中的一"中发现相关实体集合的最佳方法是什么?

  • 我无法使用 之前的 SO 查询.我的模型在运行时可定义(因此不是硬编码)这​​一事实使我无法使用查询来过滤匹配键的属性.

  • I'm unable to use a replacement query as described in a previous SO inquiry due to the latter restriction. The fact that my model is definable at runtime (and therefore isn't hardcoded) prevents me from using a query to filter properties for matching keys.

Ancestor 和其他无种类查询也因数据存储限制而无法使用,这使我无法过滤未指定种类的属性.

Ancestor and other kindless queries are also out due to the datastore limitation that prevents me from filtering on a property without the kind specified.

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

Thus far, the only idea I've had (beyond reverting to the db api) is to use a cross-group transaction to write my own reference on the "one", either by updating an ndb.StringProperty(repeat=True) containing all the related kinds when an entity of a new kind is introduced or by simply maintaining a list of keys on the "one" ndb.KeyProperty(repeat=True) every time a related "many" entity is written to the datastore.

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

I'm hoping someone more experienced than myself can suggest a better approach.

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

Given jmort253's suggestion, I'll try to augment my question with a concrete example adapted from the docs:

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

推荐答案

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

Interesting question! So basically you want to look at the Contact class and find out if there is some other model class that has a KeyProperty referencing it; in this example PhoneNumber (but there could be many).

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

I think the solution is to ask your users to explicitly add this link when the PhoneNumber class is created.

您可以通过为用户提供一个 KeyProperty 的子类来处理此问题,从而使他们更容易做到这一点;例如

You can make this easy for your users by giving them a subclass of KeyProperty that takes care of this; e.g.

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 上创建一个新属性:

Exactly how you pick the name for the collection and the value to store there is up to you; just put something there that makes it easy for you to follow the link back. The example would create a new attribute on Contact:

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

这篇关于跟踪 NDB 中未知种类的反向引用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆