Hi
You are correct,
s~cash-drawer> class SecondModel(ndb.Model):
... important_prop = ndb.StringProperty(required=True)
...
s~cash-drawer> class FirstModel(ndb.Model):
... some_prop = ndb.StringProperty()
... some_other_prop = ndb.StructuredProperty(SecondModel, required=True)
...
s~cash-drawer> model2 = SecondModel()
s~cash-drawer> model2.put()
WARNING:root:initial generator _put_tasklet(context.py:270) raised
BadValueError(Entity has uninitialized properties: important_prop)
WARNING:root:suspended generator put(context.py:733) raised
BadValueError(Entity has uninitialized properties: important_prop)
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/timh/google_appengine/google/appengine/ext/ndb/model.py",
line 3187, in _put
return self._put_async(**ctx_options).get_result()
File "/home/timh/google_appengine/google/appengine/ext/ndb/tasklets.py",
line 325, in get_result
self.check_success()
File "/home/timh/google_appengine/google/appengine/ext/ndb/tasklets.py",
line 368, in _help_tasklet_along
value = gen.throw(exc.__class__, exc, tb)
File "/home/timh/google_appengine/google/appengine/ext/ndb/context.py",
line 733, in put
key = yield self._put_batcher.add(entity, options)
File "/home/timh/google_appengine/google/appengine/ext/ndb/tasklets.py",
line 371, in _help_tasklet_along
value = gen.send(val)
File "/home/timh/google_appengine/google/appengine/ext/ndb/context.py",
line 280, in _put_tasklet
keys = yield self._conn.async_put(options, datastore_entities)
File
"/home/timh/google_appengine/google/appengine/datastore/datastore_rpc.py",
line 1542, in async_put
pbs = [self.__adapter.entity_to_pb(entity) for entity in entities]
File "/home/timh/google_appengine/google/appengine/ext/ndb/model.py",
line 562, in entity_to_pb
pb = ent._to_pb()
File "/home/timh/google_appengine/google/appengine/ext/ndb/model.py",
line 2906, in _to_pb
self._check_initialized()
File "/home/timh/google_appengine/google/appengine/ext/ndb/model.py",
line 2783, in _check_initialized
'Entity has uninitialized properties: %s' % ', '.join(baddies))
BadValueError: Entity has uninitialized properties: important_prop
s~cash-drawer> model2 = SecondModel()
s~cash-drawer> model1 = FirstModel(some_other_prop=model2)
s~cash-drawer> model1.put()
Key('FirstModel', 12001)
s~cash-drawer> model1
FirstModel(key=Key('FirstModel', 12001), some_other_prop=SecondModel())
s~cash-drawer>
However is it really a bug in NDB or NDB documentation.
Model validation is called at put() time, however a structured property
components aren't directly written to the datastore as a model in your
case. It is serialized and stored in a property of the outer model and the
only model validation that will be performed is on . You will also find
that any hooks on that model used in the structured property won't have
it's hooks called (pre_put, post_put, pre_delete . etc...)
Cheers
Tim
On Tuesday, November 4, 2014 10:43:04 PM UTC+8, Lapteuh wrote:
>
> I tested SecondModel() without parameters and result is same. Still no
> error.
>
> вторник, 4 ноября 2014 г., 19:11:40 UTC+5 пользователь timh написал:
>>
>> Not sure I would interpret it as a bug
>>
>> If you do model2 = SecondModel()
>>
>> You would get the error you expect..
>>
>> Setting a property (especiallya StringProperty) explicitly to None, is
>> not the same as not setting the value of the property.
>> The former will define the Property with a value of None, the second
>> won't define a value for the property.
>>
>> You can see this also in the how indexes work, the former will have a
>> value in the index, the later won't even have a record in the index for
>> some_other_prop
>>
>> So in my opinion it isn't a bug, but could probably do with more explicit
>> documentation.
>>
>> Just my 2c
>>
>> Cheers
>>
>> T
>>
>> On Friday, October 24, 2014 9:04:13 PM UTC+8, Lapteuh wrote:
>>>
>>> Hello. Noticed a strange behavior in the library ndb. In my opinion it
>>> looks like a bug.
>>>
>>> Example:
>>>
>>> class SecondModel(ndb.Model):
>>> important_prop = ndb.StringProperty(required=True)
>>>
>>>
>>> class FirstModel(ndb.Model):
>>> some_prop = ndb.StringProperty()
>>>
>>> some_other_prop = ndb.StructuredProperty(SecondModel, required=True)
>>>
>>>
>>> def some_func():
>>>
>>> buggy = None # attention here
>>>
>>> model2 = SecondModel(important_prop=buggy)
>>> model1 = FirstModel(some_other_prop=model2)
>>> model1.put()
>>> return
>>>
>>>
>>> Despite the fact that the code does not need to work, he works. No
>>> exception! '*required*' option in property '*important_prop*' from '
>>> *SecondModel*' just ignored.
>>>
>>
--
You received this message because you are subscribed to the Google Groups
"Google App Engine" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/google-appengine.
For more options, visit https://groups.google.com/d/optout.