且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

重复 ndb.StructuredProperty 的验证器无法触发

更新时间:2023-12-01 22:06:16

鉴于 models.py 中的这段代码:

Given this code in models.py:

class Member(ndb.Model):

    name = ndb.StringProperty()


def remove_duplicates(prop, value):
    raise Exception('Duplicate')


class Club1(ndb.Model):

    members = ndb.StructuredProperty(Member, repeated=True, validator=remove_duplicates)  

我可以创建一个Member 实例

>m = Member(name='Alice')

用这个 Member 实例创建一个 Club1 实例会触发验证:

creating a Club1 instance with this Member instance triggers the validation:

> c1 = models.Club1(members=[m])
Traceback (most recent call last):
  <snip>
  File "models.py", line 60, in remove_duplicates
    raise Exception('Duplicate')
Exception: Duplicate

但是,创建一个空的 Club1 实例然后附加一个 Member 不会:这实际上是您的测试用例.

However, creating an empty Club1 instance and then appending a Member does not: this is effectively your test case.

> c1 = models.Club1()
> c1.members.append(m)
> c1.put()
Key('Club1', 6682831673622528)

我们可以子类化ndb.StructuredProperty并将验证放在子类中:

We can subclass ndb.StructuredProperty and put the validation in the subclass:

class MembersStructuredProperty(ndb.StructuredProperty):

    def _validate(self, value):
        raise Exception('Duplicate')


class Club2(ndb.Model):

    members = MembersStructuredProperty(Member, repeated=True)

使用 Member 创建一个 Club2 实例会像以前一样触发验证:

Creating a Club2 instance with a Member triggers the validation as before:

> c2 = models.Club2(members=[m])
Traceback (most recent call last):
  <snip>
  File "models.py", line 56, in _validate
    raise Exception('Duplicate')
Exception: Duplicate

现在附加一个 Member 然后尝试写入数据存储区也是如此:

And now so does appending a Member and then trying to write to the Datastore:

> c2 = models.Club2()
> c2.members.append(m)
> c2.put()
Traceback (most recent call last):
  <snip>
  File "models.py", line 56, in _validate
    raise Exception('Duplicate')
Exception: Duplicate

因此子类化 ndb.StructuredProperty 应该允许您的测试通过.

So subclassing ndb.StructuredProperty should allow your test to pass.

我不知道为什么 ndb 的属性验证会这样,可以说这是一个错误,或者至少是未记录的行为.

正如@DanCornilescu 在评论中所观察到的,这是一个已知错误 在 SDK 中

As @DanCornilescu observes in the comments, this is a known bug in the SDK