View on GitHub

ユーザ依存の評価値の取得

Home

ユーザ依存の評価値の取得

バックエンド

マッパー

src/backend/api/online/mappers.py

class MovieMapper:
    def __init__(self, obj, rating=None):  # <- ratingを追加
        self.obj = obj
        self.rating = rating  # <- 追加

    def as_dict(self):
        movie = self.obj
        genres = [GenreMapper(movie_genre.genre).as_dict() for movie_genre in movie.movie_genres.all()]
        rating = RatingMapper(self.rating).as_dict() if self.rating else None  # <- 追加

        return {
            'movie_id': movie.movie_id,
            'title': movie.title,
            'year': movie.year,
            'genres': genres,
            'imdb_id': movie.imdb_id,
            'tmdb_id': movie.tmdb_id,
            'rating': rating,  # <- 追加
        }
......

ビュー

src/backend/api/online/views.py

......
class MoviesView(APIView):
    """映画リストビュー"""
    permission_classes = (AllowAny,)

    def get(self, request, format=None):
        """
        映画リストを取得する。

        Responses
        ---------
        movies : json
            映画リスト
        """
        # ↓追加
        # ユーザ認証
        user = _get_user(request)
        # ↑追加

        # オブジェクトの取得
        movies = Movie.objects.order_by('?')[:20]\
            .prefetch_related('movie_genres__genre')

        # ↓追加
        rating_map = {}
        if user:
            rating_map = {
                rating.movie_id: rating for rating in UserMovieRating.objects.filter(user=user)
            }
        # ↑追加

        # レスポンス
        movies_dict = [
            MovieMapper(
                movie,                                 # <- 「,」を追加
                rating=rating_map.get(movie.movie_id)  # <- 追加
            ).as_dict() for movie in movies
        ]
        data = {
            'movies': movies_dict,
        }
        return Response(data, status.HTTP_200_OK)


class MovieView(APIView):
    """映画ビュー"""
    permission_classes = (AllowAny,)

    def get(self, request, movie_id, format=None):
        """
        映画オブジェクトを取得する。

        Attributes
        ----------
        movie_id : int
            映画ID

        Responses
        ---------
        movie : json
            映画オブジェクト
        """
        # ↓追加
        # ユーザ認証
        user = _get_user(request)
        # ↑追加

        # オブジェクトの取得
        movie = get_object_or_404(
            Movie.objects.prefetch_related('movie_genres__genre'),
            pk=movie_id,
        )

        # ↓追加
        rating_map = {}
        if user:
            rating_map = {
                rating.movie_id: rating for rating in UserMovieRating.objects.filter(user=user)
            }
        # ↑追加

        # レスポンス
        data = {
            'movie': MovieMapper(
                movie,                                  # <- 「,」を追加
                rating=rating_map.get(movie.movie_id),  # <- 追加
            ).as_dict() if movie else None,
        }

        return Response(data, status.HTTP_200_OK)
......

実行確認

サインインビューの作成の手順にしたがってサインインし、アクセストークンを取得してください。取得したトークンを用いて、バックエンドサーバが起動している状態で、下記コマンドを実行してください。

$
 curl -X GET http://localhost:8000/api/online/movies/1/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

ユーザによる評価値が付与された映画データが取得できます。

下記コマンドを実行してください。

$
 curl -X GET http://localhost:8000/api/online/movies/ \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer <ACCESS_TOKEN>"

ユーザによる評価値が付与された映画リストが取得できます。確認しやすいように、映画リストでランダムに取得している箇所を一時的に下記のように修正しても良いです。

src/backend/api/online/views.py

......
class MoviesView(APIView):
    ......
    def get(self, request, format=None):
        ......
        # オブジェクトの取得
        # movies = Movie.objects.order_by('?')[:20]\
        #     .prefetch_related('movie_genres__genre')
        movies = Movie.objects.all()[:20]\
            .prefetch_related('movie_genres__genre')
......

フロントエンド

API

src/frontend/src/api/movies/getMovies.ts

......
/**
 * 映画リスト取得API
 * @returns movies - 映画リスト
 */
const getMovies = async (): Promise<{ movies: Movie[] }> => {
  const access = typeof window !== 'undefined' ? localStorage.getItem('access') : null; // <- 追加

  const url = `${context.apiRootUrl?.replace(/\/$/g, '')}/online/movies/`;
  const headers: Record<string, string> = {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    ...(access ? { Authorization: `Bearer ${access}` } : {}), // <- 追加
  };

  return await fetcher(url, {
    method: 'GET',
    headers: headers,
    cache: 'no-store',
  });
};

export default getMovies;

src/frontend/src/api/movies/getMovie.ts

......
/**
 * 映画取得API
 * @param movieId - 映画ID
 * @returns movie - 映画オブジェクト
 */
const getMovie = async (movieId: number): Promise<{ movie: Movie }> => {
  const access = typeof window !== 'undefined' ? localStorage.getItem('access') : null; // <- 追加

  const url = `${context.apiRootUrl?.replace(/\/$/g, '')}/online/movies/${movieId}`;
  const headers: Record<string, string> = {
    Accept: 'application/json',
    'Content-Type': 'application/json',
    ...(access ? { Authorization: `Bearer ${access}` } : {}), // <- 追加
  };

  return await fetcher(url, {
    method: 'GET',
    headers: headers,
    cache: 'no-store',
  });
};

export default getMovie;

ブラウザで下記それぞれの URL にアクセスしてください。

評価値を入力した後、ブラウザを更新してください。入力した評価値が維持されています。