【问题标题】:Ndb models: assure uniqueness in datastore using custom key_nameNdb 模型:使用自定义 key_name 确保数据存储的唯一性
【发布时间】:2013-07-16 08:33:41
【问题描述】:

我正在尝试模仿 Django 的 unique_together 功能,但我似乎无法理解

class MyClass(ndb.Model):
    name = 'name'
    surname = 'surname'
    phone = 'phone'

    def get_unique_key(self):
        return self.name + "|" + self.surname + "|" + self.phone

“是的,很简单”

根据this post 中接受的答案,只需在obj 构造函数中分配id 参数就足够了。但我不想在视图中处理它。理想情况下,我会这样做:

object = MyClass()
object = object.custom_populating_method(form.cleaned_data)
object.id = object.get_unique_key()
object.put()

或者甚至更好,将其放在_pre_put_hook 中,以便在保存之前将id 设置为最后一件事(并且可能进行一些检查以强制跨数据存储的数据的唯一性)。

显然,我错了。实现这一点的唯一方法是入侵视图:

unique_id = "|" + form.cleaned_data['bla'] + "|" + form.cleaned_data ...
object = MyClass(id=unique_id)

这很糟糕而且完全错误(因为模型要求的每一次更改都需要在视图中进行检查)。另外,我最终会做几个丑陋的调用来获取一些相关数据。 我可能在这个问题上花了太多时间才能看到退出,我真的希望我在这里遗漏了一些明显的东西,但我真的找不到任何好的例子,也找不到围绕这个主题的适当文档。有没有人对类似的事情有任何提示或经验?

tl;dr:有没有一种不错的方法可以在不向我的视图中添加不必要的代码的情况下实现这一点?

(我在数据存储区“使用”Django 和 ndb 的模型)

谢谢

【问题讨论】:

  • 您是否尝试过实现自己的构造函数?
  • 好吧,我尝试实现自己的 init 方法(有和没有调用超级构造函数),但没有成功
  • 除非您真的知道自己在做什么,否则您不想覆盖 init。在创建实体之前,使用工厂(类方法)构造创建键的实体。举个例子看看吹
  • @TimHoffman 我知道,我只是想了解我失败的地方
  • 基本上你不能在事后更改密钥。

标签: django google-app-engine app-engine-ndb


【解决方案1】:

使用工厂或类方法来构造实例。

class MyClass(ndb.Model):
    name = ndb.StringProperty()
    surname = ndb.StringProperty()
    phone = ndb.StringProperty()

    @staticmethod
    def get_unique_key(name,surname,phone):
        return '|'.join((name,surname,phone))

    @classmethod
    @transactional
    def create_entity(cls,keyname,name,surname,phone):
        key = ndb.Key(cls, cls.get_uniquekey())
        ent = key.get()
        if ent:
             raise SomeDuplicateError() 
        else:
            ent = cls(key=key, name=name,surname=surname,phone=phone)
            ent.put()

newobj = MyClass.create_entity(somename, somesurname, somephone)

这样做还允许您通过创建密钥并首先获取它来确保密钥是唯一的。

【讨论】:

  • 让我们稍后再说用户的电话更改(只是为了重用示例,我的用例有点不同)。我们 put() 一个新的电话号码。但是现在密钥并不能反映存储在 ndb 上的数据。有人尝试从第一次开始再次添加相同的值:(姓名,姓氏,电话)。它失败了,因为以前使用过该组合,但是如果您搜索第一个电话号码,则什么也找不到。为了避免这种情况,我考虑过删除密钥并创建一个新的 obj,但我会放弃其他模型可能对它的参考。关于如何仍然使用唯一性密钥的任何想法?
【解决方案2】:

如果你分配整个key,而不仅仅是id,我认为你可以做到这一点:

object = MyClass()
object = object.custom_populating_method(form.cleaned_data)
object.key = ndb.Key(MyClass, object.get_unique_key())
object.put()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-22
    • 2022-07-12
    • 1970-01-01
    • 2017-02-12
    • 2023-02-04
    • 2021-02-19
    • 2020-09-28
    • 1970-01-01
    相关资源
    最近更新 更多