如何构建电影数据库和用户选择?

3
我希望创建一个电影数据库,用户可以标记他/她观看和喜欢的电影:
class Movies(ndb.Model):
    watched = ndb.UserProperty()
    liked = ndb.UserProperty()

这样可以吗?我使用谷歌账户。 如何后来选择用户喜欢的所有电影?


更新。我按照 systempuntoout 的方法,使用以下代码保存用户选择:

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”)。

为什么不将默认参数传递给那些初始化为None的属性,以便每次根据您的实现将其初始化为true或false? - Jimmy Kane
2个回答

8

我会采用两个不同的模型,一个用于存储所有的电影详细信息,另一个用于存储用户选择

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 模型,以用户API中的 user_id 为键,并包含应用程序所需的所有详细属性。

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())

谢谢,这里的主要问题是如何将用户(https://developers.google.com/appengine/docs/python/users/overview)与UsersChoices链接起来? - LA_
谢谢!我已经更新了原来的问题,现在有一个新问题。 - LA_

3
看起来你正在尝试建立多对多的关系。 有几种方法可以建立这种关系(请参见多对多部分)。 还可以参考Nick's博客。(不幸的是,这两个参考资料都不是针对NDB编写的,因此,例如您不能使用collection_name,即反向引用。 但它们仍然很有用,可以帮助你将数据分解成不同的模型。)
下面是一种使用“连接表”/“关系模型”的方法:
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])

请注意,我在上面使用了投影查询,因此users_who_watched列表不会随着查询结果返回。您可能不需要这些内容,这应该可以使获取速度显着提高。
如果您预计有不到1000个用户观看或喜欢特定电影,则列表方法可能更好。
对于更高级的技术,请参见在App Engine上构建可扩展、复杂的应用程序,Brett在其中展示了如何将重复/列表属性移入单独的模型中,使用父键。

谢谢,马克。我有一个和@systempuntoout一样的问题 - 如何将这些类与用户(https://developers.google.com/appengine/docs/python/users/overview)链接起来? - LA_

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接