マイリストの作成
バックエンド
ビュー
backend/api/online/views.py
...(略)...
class MoviesRatedView(APIView):
"""評価済み映画リストビュークラス
"""
def get(self, request, format=None):
"""対象ユーザの評価済み映画リストを取得する。
Requests
--------
user_id : str
ユーザID
Response
--------
user : json
ユーザ
movies : json
映画リスト
"""
# ユーザ認証
user_id = request.GET.get('user_id') if 'user_id' in request.GET else None
# オブジェクトの取得
reclist = []
if user_id:
reclist = Rating.objects.filter(user_id=user_id).order_by('-rated_at')\
.select_related('movie', 'user')\
.prefetch_related('movie__genres')\
.prefetch_related(
Prefetch(
'movie__movie_ratings',
queryset=Rating.objects.filter(user_id=user_id),
to_attr='user_ratings'
)
)
user = User.objects.get(id=user_id)
user_dict = UserMapper(user).as_dict()
# レスポンス
movies = [rec.movie for rec in reclist]
movies_dict = [MovieMapper(movie).as_dict(user_id) for movie in movies]
data = {
'user': user_dict,
'movies': movies_dict,
}
return Response(data, status.HTTP_200_OK)
URLマッピング
backend/api/online/urls.py
from django.urls import path
from . import views
urlpatterns = [
path('users/', views.UsersView.as_view()),
path('movies/', views.MoviesView.as_view()),
path('movies/<int:id>/', views.MovieView.as_view()),
path('ratings/', views.RatingsView.as_view()),
path('movies_popularity/', views.MoviesPopularityView.as_view()),
path('movies_movies_movies/', views.MoviesMoviesMoviesView.as_view()),
path('movies_bpr/', views.MoviesBPRView.as_view()),
path('movies_rated/', views.MoviesRatedView.as_view()), # <- 追加
]
ブラウザで下記それぞれのURLにアクセスしてください。
- http://localhost:8000/api/online/movies_rated/?user_id=00000000-0000-0000-0000-000000000001
- http://localhost:8000/api/online/movies_rated/?user_id=【ユーザID】
user_id
を変えてアクセスると、ユーザごとに評価済みの映画リストが表示されます。
フロントエンド
API
frontend/src/services/movies/getMoviesRated.ts
import { ApiContext, Movie, User } from '@/types/data';
import { fetcher } from '@/utils';
const context: ApiContext = {
apiRootUrl: process.env.NEXT_PUBLIC_API_BASE_URL,
};
/**
* 評価済み映画リスト取得API
* @param user - ユーザ
* @returns 映画リスト
*/
const getMoviesRated = async (user: User): Promise<{ movies: Movie[] }> => {
const userParam = user ? `?user_id=${user.id}` : '';
return await fetcher(`${context.apiRootUrl?.replace(/\/$/g, '')}/movies_rated/${userParam}`, {
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
cache: 'no-store',
});
};
export default getMoviesRated;
コンポーネント
frontend/src/app/components/ui/AccountMenu.tsx
...(略)...
export default function AccountMenu() {
...(略)...
return (
<React.Fragment>
...(略)...
<Menu
...(略)...
>
<MenuItem onClick={handleClose}>
<Avatar />
<Link href="/myaccount/">My account</Link>
</MenuItem>
{/* ↓追加 */}
<MenuItem onClick={handleClose}>
<Avatar /> <Link href="/mypage/">My page</Link>
</MenuItem>
{/* ↑追加 */}
<Divider />
...(略)...
</Menu>
</React.Fragment>
);
}
ページ
frontend/src/app/mypage/page.tsx
import React from 'react';
import { auth } from '@/auth';
import getMoviesRated from '@/services/movies/getMoviesRated';
import connectUser from '@/services/users/connectUser';
import getUser from '@/services/users/getUser';
import MovieList from '../components/movie/MovieList';
import MovieListBPR from '../components/movie/MovieListBPR';
const PER_PAGE = 5;
const MyPage = async () => {
await connectUser();
const session = await auth();
const user = session ? await getUser(session?.user?.email!) : null;
const { movies } = await getMoviesRated(user!);
const phrase = 'マイリスト';
return (
<>
{session?.user ? (
<>
<MovieList phrase={phrase} movies={movies} perPage={PER_PAGE} user={user!} />
<MovieListBPR user={user!} perPage={PER_PAGE} />
</>
) : (
<></>
)}
</>
);
};
export default MyPage;
ブラウザで下記URLにアクセスするか、アカウントメニューからMy pageをクリックすると、マイリストのページが表示されます。