3

映画データベースを作成したいと思います。このデータベースでは、ユーザーが視聴して気に入った映画にマークを付けることができます。

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

それは機能しますか?私はGoogleアカウントを使用しています。ユーザーが気に入ったすべての映画を後でどのように選択すればよいですか?


Upd。私は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、と同じが使用されます)。watchedNone

4

2 に答える 2

8

私は2つの異なるモデルを使用します。1つはすべてのMovies詳細を保存し、もう1つは:を保存し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()

ユーザーに関する情報を保存する必要がある場合は、ユーザーAPIからキーを指定して、アプリケーションに必要なすべての詳細プロパティを使用してUserInfoモデルを作成する必要があります。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())
于 2012-07-30T15:43:18.743 に答える
3

多対多の関係をモデル化しようとしているようです。 この関係をモデル化する方法はいくつかあります(多対多のセクションを参照)。Nickのブログも参照してください。(残念ながら、これらの参照はどちらもNDB用に記述されていないため、たとえば、逆参照を使用することはできませんcollection_name。ただし、データをさまざまなモデルに分割する方法を示すのに役立ちます。)

「テーブルの結合」/「関係モデル」を使用して、これを行う1つの方法を次に示します。

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リストがクエリ結果とともに返されないことに注意してください。これらはおそらく必要ありません。これにより、フェッチが大幅に高速化されます。

たとえば、1,000人未満のユーザーが特定の映画を視聴したり、気に入ったりすることが予想される場合は、リストアプローチの方が適している可能性があります。

より高度な手法については、App Engineでのスケーラブルで複雑なアプリの構築を参照してください。Brettは、親キーを使用して、repated/listプロパティを別のモデルに移動する方法を示しています。

于 2012-07-30T16:20:19.733 に答える