評価値の登録と取得
モデル
backend/api/online/models.py
...(略)...
class Rating(models.Model):
"""評価値モデル
Attributes
----------
id : TextField
評価値ID
user : ForeignKey[User]
対象ユーザ
movie : ForeignKey[Movie]
対象映画
rating : IntegerField
評価値
rated_at : DateTimeField
評価日時
"""
id = models.TextField(primary_key=True, max_length=43)
user = models.ForeignKey(User, on_delete=models.CASCADE)
movie = models.ForeignKey(Movie, related_name='movie_ratings', on_delete=models.CASCADE)
rating = models.FloatField(blank=False, null=False)
rated_at = models.DateTimeField(blank=False, null=False, auto_now=True)
class Meta:
managed = True
db_table = 'ratings'
def __str__(self):
return '{}:{}:{}'.format(self.user.id, self.movie.id, self.rating)
マイグレーション
(recsys_full) backend$ python manage.py makemigrations online --settings config.settings.development
Migrations for 'online':
api/online/migrations/0003_rating.py
+ Create model Rating
(recsys_full) backend$ python manage.py migrate --settings config.settings.development
テーブルの確認
recsys_full=# \dt
List of relations
Schema | Name | Type | Owner
--------+----------------------------+-------+-------
...(略)...
public | ratings | table | rsl
public | users | table | rsl
(15 rows)
recsys_full=# \d ratings
Table "public.ratings"
Column | Type | Collation | Nullable | Default
----------+--------------------------+-----------+----------+---------
id | text | | not null |
rating | double precision | | not null |
rated_at | timestamp with time zone | | not null |
movie_id | integer | | not null |
user_id | uuid | | not null |
Indexes:
"ratings_pkey" PRIMARY KEY, btree (id)
"ratings_id_b3cd9389_like" btree (id text_pattern_ops)
"ratings_movie_id_c828f845" btree (movie_id)
"ratings_user_id_dbf12542" btree (user_id)
Foreign-key constraints:
"ratings_movie_id_c828f845_fk_movies_id" FOREIGN KEY (movie_id) REFERENCES movies(id) DEFERRABLE INITIALLY DEFERRED
"ratings_user_id_dbf12542_fk_users_id" FOREIGN KEY (user_id) REFERENCES users(id) DEFERRABLE INITIALLY DEFERRED
マッパー
backend/api/online/mappers.py
...(略)...
class RatingMapper:
def __init__(self, obj):
self.obj = obj
def as_dict(self):
rating = self.obj
return {
'id': rating.id,
'user_id': rating.user_id,
'movie_id': rating.movie_id,
'rating': rating.rating,
'rated_at': rating.rated_at,
}
ビュー
backend/api/online/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import User, Movie, Rating # <- Ratingを追加
from .mappers import UserMapper, MovieMapper, RatingMapper # <- RatingMapperを追加
from .utils import hash
import uuid
...(略)...
# ↓追加
class RatingsView(APIView):
"""評価値ビュークラス
"""
def get(self, request, format=None):
"""評価値を取得する。
Requests
--------
id : str
評価値ID
Response
--------
ratings : json
評価値リスト
"""
# リクエストパラメタの取得
id = request.GET.get('id')
# オブジェクトの取得
ratings = Rating.objects.filter(id=id)
# レスポンス
ratings_dict = [RatingMapper(rating).as_dict() for rating in ratings]
data = {
'ratings': ratings_dict,
}
return Response(data, status.HTTP_200_OK)
def post(self, request, format=None):
"""評価値を登録する。
Requests
--------
id : str
評価値ID
user_id : str
ユーザID
movie_id : int
映画ID
rating : float
評価値
Response
--------
rating : json
評価値
"""
# リクエストパラメタの取得
id = request.data['id']
user_id = request.data['user_id']
movie_id = request.data['movie_id']
rating = request.data['rating']
# オブジェクトの登録
user = User.objects.get(pk=user_id)
movie = Movie.objects.get(pk=movie_id)
rating_model = Rating(id=id, user=user, movie=movie, rating=rating)
rating_model.save()
# レスポンス
rating_dict = RatingMapper(rating_model).as_dict()
data = {
'rating': rating_dict,
}
return Response(data, status.HTTP_201_CREATED)
# ↑追加
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()), # <- 追加
]
ブラウザで下記URLにアクセスしてください。
ユーザAPIの実装で登録された【ユーザID】を使って、Contentフォームに、例えば下記のデータを入力し、POSTボタンをクリックしてください。
{
"id": "【ユーザID】_000001",
"user_id": "【ユーザID】",
"movie_id": 1,
"rating": 3.5
}
ratings
テーブルに下記のように評価値が登録されました。
recsys_full=# SELECT * FROM ratings;
id | rating | rated_at | movie_id | user_id
-------------------+--------+-------------------------------+----------+-------------
【ユーザID】_000001 | 3.5 | 2025-03-22 15:25:25.670634+09 | 1 | 【ユーザID】
(1 row)
ブラウザで下記URLにアクセスしてください。
下記のように、登録した評価値のデータが取得できます。
{
"ratings": [
{
"id": "【ユーザID】_000001",
"user_id": "【ユーザID】",
"movie_id": 1,
"rating": 3.5,
"rated_at": "2025-03-22T06:25:25.670634Z"
}
]
}
同じ映画に対して、再度、評価値を変えて登録してみると、ratings
テーブルの内容が更新されます。
データの登録
一旦、users
テーブルとratings
テーブルの内容を削除したうえで、既存ユーザおよび評価値データを登録しておきます。
recsys_full=# DELETE FROM ratings;
recsys_full=# DELETE FROM users;
offline/data$
psql recsys_full -U postgres -c "\copy users (id, email_encrypted, email_hash) from 'users.csv' with delimiter E'\t' csv header encoding 'UTF8'"
psql recsys_full -U postgres -c "\copy ratings (id, user_id, movie_id, rating, rated_at) from 'ratings.csv' with delimiter E'\t' csv header encoding 'UTF8'"
データの確認
recsys_full=# SELECT * FROM users;
recsys_full=# SELECT * FROM ratings;