跟踪 NDB 中未知种类的反向引用 [英] Following backreferences of unknown kinds in 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屋!