Using ndb.KeyProperty how to reference the same model?
Asked Answered
E

2

9

I have a simple scenario where there is a User class which has the name, email and followers property.

class User(ndb.Model):
    name = ndb.StringProperty(required = True)
    search_name = ndb.StringProperty(required = True)
    pw_hash = ndb.StringProperty(required = True)
    email = ndb.StringProperty()

    follows = ndb.KeyProperty(Follow, repeated=True)
    followers = ndb.KeyProperty(User, repeated=True)

While executing this I am getting the error.

File "C:\ujjal\my project\cravel\code2\Users.py", line 46, in User
  followers = ndb.KeyProperty(User, repeated=True)
NameError: name 'User' is not defined
INFO     2012-09-11 11:45:23,953 dev_appserver.py:2967] "GET / HTTP/1.1" 500 -

Any suggestion as to how model the "followers" attribute would be highly appreciated. Thanks in Advance

Esther answered 11/9, 2012 at 11:47 Comment(0)
W
31

Using a kind on a key property e.g. some_prop = ndb.KeyProperty(User) only enforces that the kind of the key must be of kind User. So you can still use a KeyProperty without a kind if need be.

However, if you want to enforce that all follower keys must be of kind User(inside the User model) then surround the kind with quotes:

followers = ndb.KeyProperty(kind='User', repeated=True)

It's explained a little better in the ndb cheat sheet

Waldheim answered 11/9, 2012 at 14:0 Comment(1)
This problem is not ndb specific. You cannot reference a class by its type until after the class is defined. That is why ndb allows you to use a string name for a kind or the python type object.Tymbal
S
2

If you just want "followers" to be a KeyProperty then just put:

followers = ndb.KeyProperty(repeated=True)

or, what I think you are after, to specify the type of key.

follows = ndb.KeyProperty(kind=User,repeated=True)

I think you are just missing kind=User probably.

https://developers.google.com/appengine/docs/python/ndb/properties#types

Slype answered 11/9, 2012 at 12:34 Comment(5)
I tried kind=User but it didnt work. The first one worked though. But still not very clear why the kind=User or simply User wont work.Esther
Personally I'd avoid using User as a name. It has too much potential for clashing. Suggest rename, retry. But using kind just makes sure that when you assign a key it's of that particular kind. You can also put the name of the model in quotes as a string, it does not matter which you use in fact so try that also.Slype
thanks for your input. You are correct, by putting the kind in '' solves the issue. One thing that I dont get is your comment Personally I'd avoid using User as a name. It has too much potential for clashing Can you explain a little bit more?Esther
I just meant that if you ever (for example) start to use the users service you might want to say: user = users.User("[email protected]") and there is also a UserProperty in db/ndb. So having your own class called "User" won't help keep them all separate either in the code or your mind. It's just my personal preference.Slype
got it, and agree with you to use the UserProperty/users.User(...) will be a better approach. I will check that out, thanks for the inputEsther

© 2022 - 2024 — McMap. All rights reserved.