How to structure movies database and user choices?

前端 未结 2 1984
梦如初夏
梦如初夏 2021-01-01 07:47

I would like to create movies database, where user will be able to mark movies he/she watched and liked:

class Movies(ndb.Model):
    watched = ndb.UserPrope         


        
相关标签:
2条回答
  • 2021-01-01 08:13

    I would go with two different Models, one that stores all the Movies details and one to store the 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()
    

    If you need to store informations about users you should create your UserInfo Model, keyed by user_id from the users API, with all the details Properties your application needs.

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

    To create a new UserInfo, you could do:

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

    Then, when the user is logged in, use his/her user_id to retrieve the watched/liked movies.

    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 讨论(0)
  • 2021-01-01 08:13

    It appears you are trying to model a many-to-many relationship. There are a few ways to model this relationship (see the Many-to-Many section). See also Nick's blog. (Unfortunately, neither of those references are written for NDB, so, for example, you can't use collection_name, i.e., back-references. But they are still useful in showing you how to break up the data into different models.)

    Here's one way you could do it, using "join tables"/"relationship models":

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

    Depending on how many users your application will support, and how often the database will be updated, it may be more efficient to use repeated properties (i.e., lists of users) instead of join tables:

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

    Note that I used a projection query above, so that the users_who_watched lists are not returned with the query results. You probably don't need these, and this should make fetching significantly faster.

    If you expect, say, less than 1,000 users to watch or like a particular movie, the list approach might be better.

    For a more advanced technique, see Building Scalable, Complex Apps on App Engine, where Brett shows how to move the repeated/list property into a separate model, using parent keys.

    0 讨论(0)
提交回复
热议问题