While the NDB documentation says:
Although a StructuredProperty can be repeated and a StructuredProperty can contain another StructuredProperty, beware: if one structured property contains another, only one of them can be repeated.
It appeared to me that the clearest interpretation of the documentation may be properly written as "if one structured property contains another structured property".
In which case, I would expect something like this to work:
class KeyList(ndb.Model):
keys = ndb.KeyProperty(repeated=True)
class Collection(ndb.Model):
lists = ndb.StructuredProperty(KeyList, repeated=True)
However, this fails with the error:
TypeError: This StructuredProperty cannot use repeated=True because its model class (KeyList) contains repeated properties (directly or indirectly).
It appears that one cannot nest any repeated property inside a repeated StructuredProperty.
From the code, this looks to be the intended behaviour.
In which case the development appserver may differ from the documented behaviour. If the documentation as I've read it is correct, then a fix for the condition in the development server giving rise to the above error might be something like:
if modelclass._has_repeated and isinstance(modelclass, StructuredProperty):
# ...
Should an AppEngine StructuredProperty be able to contain repeated properties (other than a repeated StructuredProperty)?
Issue report is here: https://github.com/GoogleCloudPlatform/appengine-python-vm-runtime/issues/40
EDIT It's worth noting that the golang docs say this:
Slices of structs are valid, as are structs that contain slices. However, if one struct contains another, then at most one of those can be repeated. This disqualifies recursively defined struct types: any struct T that (directly or indirectly) contains a []T.
The implication I take from this is that repeated non-struct properties on repeated structs are not inherently prohibited at the BigTable level, but rather a side-effect of the Python implementation.
Without further corroboration I would not rely on this implication.