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

Evan Plaice
  • 13,944
  • 6
  • 76
  • 94
ujjalcal
  • 125
  • 1
  • 1
  • 5

2 Answers2

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

Rob Curtis
  • 2,245
  • 24
  • 33
  • 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. – Josh J Apr 30 '15 at 19:54
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

Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
Paul Collingwood
  • 9,053
  • 3
  • 23
  • 36
  • 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. – ujjalcal Sep 11 '12 at 12:59
  • 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. – Paul Collingwood Sep 11 '12 at 13:13
  • 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? – ujjalcal Sep 11 '12 at 14:13
  • I just meant that if you ever (for example) start to use the users service you might want to say: user = users.User("Albert.Johnson@example.com") 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. – Paul Collingwood Sep 11 '12 at 14:17
  • 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 input – ujjalcal Sep 11 '12 at 14:40