3

我想创建电影数据库,在这里用户可以标记的电影,他/她看到并喜欢:如何构建电影数据库和用户选择?

class Movies(ndb.Model): 
    watched = ndb.UserProperty() 
    liked = ndb.UserProperty() 

请问这项工作?我使用Google帐户。 我应该如何选择后来用户喜欢的所有电影?


Upd。我已经按照systempuntoout approach和使用下面的代码保存用户选择:

user = users.get_current_user() 
if user: 
    userschoices = models.UsersChoices(
     movie=ndb.Key(models.Movies, movie_id), # TODO: what if movie_id is wrong? 
     watched=True, 
     user_id=user.user_id() 
     ) 
    try: 
     userschoices.put() 
     self.response.out.write('1') 
    except: 
     self.response.out.write('0') 

但是,如果用户做出选择几次,然后几个记录添加到数据存储... 岂不是更好只是将用户ID和电影ID保存为关键字?

userschoices = models.UsersChoices.get_by_id(user.user_id() + '-' + movie_id) 
if userschoices is None: 
    userschoices = models.UsersChoices(id=user.user_id() + '-' + movie_id) 
userschoices.movie = ndb.Key(models.Movies, movie_id) # TODO: what if movie_id is wrong? 
userschoices.user_id = user.user_id() 
if option == 'liked': 
    userschoices.liked = True 
elif option == 'watched': 
    userschoices.watched = True 

然而,利用这样的方法,如果我没有通过liked,然后它覆盖了与None值(与watched一样,如果没有通过,则使用None)。

+0

为什么不将默认参数传递给初始化为None的属性,以便每次都根据您的实现使用true或false进行初始化 – 2013-01-05 12:59:46

回答

8

我会用两种不同的模式,一种是存储所有Movies细节和一个去存储UserChoices

class Movies(ndb.Model): 
    title = ndb.StringProperty(required=True) 
    director = ndb.StringProperty() 
    whatever = ndb.StringProperty() 

class UsersChoices(ndb.Model): 
    movie = ndb.KeyProperty(kind=Movies, required=True) 
    watched = ndb.BooleanProperty(required=True) 
    liked = ndb.BooleanProperty(required=True) 
    user_id = ndb.StringProperty(required=True) 

    @classmethod 
    def get_liked_movies(cls, user_id): 
     return cls.query(cls.user_id == user_id, cls.liked == true).fetch(10) 

    @classmethod 
    def get_watched_movies(cls, user_id): 
     return cls.query(cls.user_id == user_id, cls.watched == true).fetch(10) 

    @classmethod 
    def get_by(cls, user_id, movie_key): 
     return cls.query(cls.user_id == user_id, cls.movie == movie_key).get() 

如果您需要存储有关用户的信息,你应该创建UserInfo模型,通过键控user_idusers API,与应用程序需要的所有细节属性。

class UserInfo(ndb.Model): 
     #Keyed by user_id 
     nickname = ndb.StringProperty() 
     email = ndb.StringProperty() 

要创建一个新UserInfo,你可以这样做:

from google.appengine.api import users 

user = users.get_current_user() 
userinfo = UserInfo(
     id = user.user_id(), 
     nickname = user.keyname(), 
     email = user.email() 
    ) 
userinfo.put() 

然后,当用户登录,使用他/她user_id检索观看/喜欢的电影。

from google.appengine.api import users 

user = users.get_current_user() 
userinfo = ndb.Key(UserInfo, user.user_id()).get() 
watched_movies = UsersChoices.get_watched_movies(userinfo.key.id()) 
liked_movies = UsersChoices.get_liked_movies(userinfo.key.id()) 
+0

谢谢,这里的主要问题是如何链接用户(https ://developers.google.com/appengine/docs/python/users/overview)与UsersChoices? – 2012-07-30 18:58:54

+0

谢谢!我已经用我现在的问题更新了原始问题 – 2012-08-06 19:42:08

3

看来您正在试图建立一个多对多的关系。 There are a few ways to model this relationship(参见多对多部分)。另见Nick's blog。 (不幸的是,这些引用是为NDB编写的,因此,例如,you can't use collection_name, i.e., back-references,但他们仍然在向你展示如何将数据分解成不同型号的有用。)

这里是你可以做的一种方式,使用“连接表” /“关系模型”:

class Movie(ndb.Model): 
    title = ndb.StringProperty(required=True) 

class LikedMovie(ndb.Model): 
    movie = ndb.KeyProperty(kind=Movie, required=True) 
    user = ndb.StringProperty(required=True) # user.user_id() 

class WatchedMovie(ndb.Model): 
    movie = ndb.KeyProperty(kind=Movie, required=True) 
    user = ndb.StringProperty(required=True) # user.user_id() 

... 
    movies_user_likes = LikedMovie.query(LikedMovie.user == user.user_id()).fetch() 

根据您的应用程序将支持的用户数,以及多久数据库将被更新,它可能是更有效地使用重复的属性(即列表的用户)而不是连接表:

class Movie(ndb.Model): 
    title = ndb.StringProperty(required=True) 
    users_who_watched = ndb.StringProperty(repeated=True) # list of user.user_id()s 
    users_who_liked = ndb.StringProperty(repeated=True) # list of user.user_id()s 

... 
    movies_user_likes = Movie.query(Movie.users_who_liked == user.user_id()).fetch(projection=[Movie.title]) 

请注意,我使用上面的projection query,以便users_who_watched列表不会与查询结果一起返回。你可能不需要这些,这应该使得取得更快。

如果您希望少于1,000位用户观看或喜欢某部电影,则列表方式可能会更好。

有关更高级的技术,请参阅Building Scalable, Complex Apps on App Engine,其中Brett演示了如何使用父键将重复/列表属性移动到单独的模型中。

+0

谢谢,马克。我对@systempuntoout提出了同样的问题 - 如何将这些类与用户相关联(https://developers.google.com/appengine/docs/python/users/overview)? – 2012-07-30 19:14:56