📘 DRF  


🔗 [👤기능구현] 이전에 만든 movie 수정 및 Genre model 생성

이 글에서 이어지는 내용이에요.

movie preference 관련해서 미완성했는데,

딱! zep에 들어갔을 때 팀원분이 계시더라고요.

그래서 코드 보여드리면서 보완 및 완성한 코드예요.

2025년 2월 23일 일요일


목차

  1. movies.models.py
  2. CSV 파일을 SQLite에 이식하기
  3. views.py

⚙️ movies/models.py

1️⃣ Movie Model

더보기
"""Movie model"""
class Movie(models.Model):
    id = models.CharField(max_length=100, primary_key=True)  # TMDB ID(기존 데이터셋의 ID)
    title = models.CharField(max_length=100)  # 제목
    revenue = models.IntegerField(default=0)  # 수익
    vote_average = models.FloatField(default=0.0)  # 평점
    imdb_id = models.CharField(max_length=100, default="")  # IMDB ID
    original_title = models.CharField(max_length=100)  # 원제(개봉국가제목)
    overview = models.TextField(default="")  # 줄거리
    popularity = models.FloatField(default=0.0)  # 인기도
    genres = models.CharField(max_length=100, default="")  # 장르
    poster_path = models.CharField(max_length=100, default="")  # 포스터 경로(url)
    keywords = models.CharField(max_length=100, default="")  # 키워드

    def __str__(self):
        return self.title

2️⃣ Movie Preference Model

더보기
"""영화 선호도 정리를 위한 model"""
class MoviePreference(models.Model):
    user_id_fk = models.ForeignKey(User, on_delete=models.CASCADE, related_name='genre_preference')# FK "유저 ID"
    movie_id_fk = models.ForeignKey(Movie, on_delete=models.CASCADE, related_name='movie_preference') # FK "영화 ID"
    preference_type = models.CharField(
        max_length=10,
        choices=[('like', 'Like'), ('dislike', 'Dislike')],
        default='dislike') # 선호도 유형 like, dislike

    def __str__(self):
        return f"{self.user_id_fk} liked/disliked {self.movie_id_fk}."

3️⃣ Genre Preference Model

더보기
"""장르 선호도 정리를 위한 model"""
class GenrePreference(models.Model):
    user_id_fk = models.ForeignKey(User, on_delete=models.CASCADE) # FK 유저 ID
    genre_id = models.CharField(max_length=100, default="", unique=True)
    preference_type = models.CharField(
        max_length=10,
        choices=[('like', 'Like'), ('dislike', 'Dislike')],
        default='dislike') # 선호도 유형 like, dislike
        
    def __str__(self):
        return f"{self.user_id_fk} liked/disliked {self.genre_id_fk}."

⚙️ SQLite에 CSV 내용 넣기

1️⃣ 시작 전에!

더보기
"""
이 스크립트를 실행하기 전에 다음 단계를 따라주세요:

1. Python 가상환경 생성 및 활성화:
   - Windows:
     python -m venv .venv
     .venv\Scripts\activate
   - Mac/Linux:
     python3 -m venv .venv
     source .venv/bin/activate

2. 필요한 패키지 설치:
   프로젝트 루트의 DRF-Backend 디렉토리에서:
   pip install -r requirements.txt

3. 데이터 파일 준비:
   - 프로젝트 루트에 'dataset' 폴더 생성
   - 'dataset' 폴더에 'revised_df.csv' 파일 위치

4. 데이터베이스 마이그레이션:
    python manage.py migrate

5. 스크립트 실행:
   python -m movies.import_movies
"""

2️⃣ 시~작!

더보기
import os
import sys

# 프로젝트 루트를 sys.path에 추가하여 import 문제를 방지합니다.
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))

# Django 설정 모듈을 지정합니다.
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "main.settings")
import django

django.setup()

from movies.models import Movie

import csv
from datetime import datetime


def import_movies(file_path):
    try:
        with open(file_path, "r", encoding="utf-8") as file:
            reader = csv.DictReader(file)
            count = 0
            for row in reader:
                try:
                    Movie.objects.create(
                        id=row["id"],
                        title=row["title"],
                        revenue=row["revenue"],
                        vote_average=row["vote_average"],
                        imdb_id=row["imdb_id"],
                        original_title=row["original_title"],
                        overview=row["overview"],
                        popularity=row["popularity"],
                        genres=row["genres"],
                        poster_path=row["poster_path"],
                        keywords=row["keywords"],
                    )
                    count += 1
                except Exception as e:
                    print(
                        f"Error importing movie {row.get('title', 'unknown')}: {str(e)}"
                    )
            print(f"Successfully imported {count} movies")
    except FileNotFoundError:
        print(f"Error: Could not find the CSV file at {file_path}")
        print("Please make sure the CSV file exists in the dataset directory")
        sys.exit(1)
    except Exception as e:
        print(f"Error reading the CSV file: {str(e)}")
        sys.exit(1)


if __name__ == "__main__":
    # 프로젝트 루트 디렉토리 기준으로 상대 경로 설정
    project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), "../.."))
    csv_file_path = os.path.join(project_root, "dataset", "revised_df.csv")

    print(f"Looking for CSV file at: {csv_file_path}")
    import_movies(csv_file_path)

from movies.models import Movie
  • 저희는 movies라는 app에 있는 Movie 모델을 쓸 거예요.
for row in reader:
    try:
        Movie.objects.create(
            id=row["id"],
            title=row["title"],
            revenue=row["revenue"],
            vote_average=row["vote_average"],
            imdb_id=row["imdb_id"],
            original_title=row["original_title"],
            overview=row["overview"],
            popularity=row["popularity"],
            genres=row["genres"],
            poster_path=row["poster_path"],
            keywords=row["keywords"],
            )
  • 이 부분은 사용하시는 모델에 맞게끔 변경해주세요.
  • 칼럼을 만들고 그 칼럼의 행에 값을 넣는 작용이에요.

 

그러면 CSV 파일에 있던 값들이 이렇게 SQLite에 들어가게 돼요!

얏호~!


⚙️ movies/urls.py

더보기
from django.urls import path
from . import views

urlpatterns = [
    path('movielist/', views.SignUpMovieListView.as_view()), # Signup movie list로 가기
]

⚙️ movies/views.py

더보기
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status
import random

from .models import Movie
from .serializers import SignupMovieListSerializer

"""랜덤한 영화 리스트 25개 보여주는 코드"""
class SignUpMovieListView(APIView):

    def get(self, request):
        # 평점 내림차순으로 정렬하고 수익이 3억 달러 이상인 영화 100개 필터링
        top_movies = Movie.objects.filter(revenue__gte=300000000).order_by(
        "-vote_average")[:100]  # 수익이 3억 달러 이상인 영화 중 상위 100개 선택

        # 100개 중 랜덤으로 25개 선택
        random_movies = list(top_movies)  # 쿼리셋을 리스트로 변환
        random_selection = random.sample(
            random_movies, min(25, len(random_movies))
        )  # 랜덤으로 25개 영화 선택

        # 선택된 영화들을 직렬화
        serializer = SignupMovieListSerializer(random_selection, many=True)

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

SignupMovieListSerializer

더보기
"""회원가입 시, 보여지는 영화 포스터 리스트 및 장르"""
class SignupMovieListSerializer(serializers.ModelSerializer):
    
    class Meta:
        model = Movie
        fields = ['id', 'original_title', 'poster_path']
        read_only_fields = ['id']

Postman

프런트가 없어서 postman의 존재가 너무 감사해요 ㅠㅠㅠㅠ 으흐흑

 

일단 저희가 제작한 서비스는 로그인을 해야 접근이 가능해서

Headers에 Authorization - Bearer로 토큰을 집어넣어 줘요.

그러고 url을 movie/movielist/로 들어가서 Send를 해주면,

 

movie-id, original_title, poster_path로 총 25개 랜덤으로 보여줍니다!

 

 

이제는 선호하는 영화를 5개를 입력하면 저렇게 성공했다는 메시지가 떠요.

 

movie preference
genre preference

짜잔~!

DB에도 저장이 잘 되어 있음을 알 수 있어요!

 

 

5개 이상이면 error 메시지도 잘 뜨네요!

🐾Recent posts