validator for repeated ndb.StructuredProperty fails to fire

梦想的初衷 提交于 2019-12-06 06:09:16

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)  

I can create a Member instance

> m = Member(name='Alice')

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

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)

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)

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

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

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

I don't know why ndb's property validation behaves like this, arguably it's a bug, or at least undocumented behaviour.

EDIT:

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!