View
내가 구현하고 싶었던 기능
: 1차 프로젝트를 시작하며, 내가 구현하고 싶었던 기능은 한국영화와 외국영화의 리스트를 얻는 것이었다.
class MovieView(View):
def get(self,request):
country_name = request.GET.get("country")
LIMIT = 25
OFFSET = 0
if not country_name:
return JsonResponse({"MESSAGE" : "PARAMETER_DOSE_NOT_EXIST"}, status=400)
country_name == "한국"
movies = Movie.objects.filter(country__name="한국").order_by('-id')[OFFSET : LIMIT]
if country_name == "외국":
movies = Movie.objects.exclude(country__name="한국")[OFFSET : LIMIT]
처음에 위 코드로 한국 영화 리스트는 잘 불러와졌다.
추가로 이번엔 외국영화를 호출 해보았다. 언뜻 보기에는 아래와 같이 외국영화들이 잘 호출 되는 것 처럼 보였으나.....
나타난 문제
: 위에서 얻은 영화리스트에 만족하고 있던 찰나, 밑으로 쭉 스크롤을 내려보니.... 아뿔싸!!!!!!???????
한국이라는 나라이름만 안나왔지 한국영화도 같이 출력이되는 것이 보였다.
보이는 것처럼 나라이름에 null 값이 들어간 상태로 출력이 되는 것이 아닌가??????????
이것 때문에 ㅜㅜㅜ 3일간을 머리싸매고 방법을 궁리하였다.......
해결방법
country = Country.objects.exclude(name="한국")로 접근하여 country.movie_set.all()로 한국을 제외한 나라들이 명단을 뽑을지.....궁리하였으나,반복문을 너무 많이 사용하게 되며, 쿼리셋과 쿼리셋을 연산하여 더해주어야 문제가 발생하였다.
쿼리셋을 연산하는 방법을 찾아보았지만,,, 당장 이해하기는 어려워 다음 프로젝트때 만날 날을 기약하였다.
그리고 다른 여러가지 방법을 찾아보다가 다시 처음으로 돌아와,
기능 구현에 핵심적인 문제가 무엇이었는지 생각해보았다.
핵심은 exclude 함수를 사용하여 한국이라는 나라를 분명 제외 하였는데,
나라 이름을 null로 가져오면서, 영화정보도 함께 가져와지는 것이었다!!!
그렇다면, 나는 나라이름이 null 값인 영화를 허용하지만 않으면 되는 것아닌가????????
그래서 null값을 허용하지 않는 속성을 찾아보기위해 구글링을 하였다.
먼저 머릿속에 떠오르는대로 djnago exclude null이라는 키워드로 검색을 하였고,
아래와 같은 문서를 발견하였다.
위 예시대로 곧장 코드를 아래와 같이 적용해 보았고,
if country_name == "외국":
movies = Movie.objects.exclude(country__name="한국").filter(country__name__isnull = False).distinct().order_by('-id')[OFFSET : LIMIT]
나는 결국 다음과 같은 결과를 얻을 수 있었다.
흑흑 주여........... 감사합니다..........
너무 기뻐 감격의 환성을 질렀다.....ㅋㅋ
이와 동일한 방법을 적용했더니, 장르별로 영화를 가져오는 코드를 작성하는 것도 훨씬 쉬웠다.
Null...다시는 잊지 못할것 같다........l....... filter(field_isnull = False)
Thinking Melody
그리하여 이 사건을 통하여 나는, 개발자는 코드만 잘 짜는 것이 중요한게 아니라,
내가 원하는 대로 데이터가 잘 가져와 지는 지 확인하는 과정이 정말 중요하다는 생각을 하게되었다.
또한, 어쩌면 내가 지금 겪는 이 문제는 어쩌면 정말 별거 아닌 간단한 문제 일 수도 있으니,
앞으로도 조급해 하지말고 가장 근본적인 문제가 무엇이었는지,
처음으로 돌아가 천천히 문제를 짚어 나가는 침착함을 발휘해야겠다고 다짐하였다.
👇 최종 결과물
import json
from django.views import View
from django.http import JsonResponse
from movies.models import Movie, Rating
from users.models import User
class MovieView(View):
def get(self,request):
country_name = request.GET.get("country")
genre1 = request.GET.get("genre1")
genre2 = request.GET.get("genre2")
rating = request.GET.get("rating")
LIMIT = 25
OFFSET = 0
if not country_name and not genre1 and not genre2 and not rating:
return JsonResponse({"MESSAGE" : "PARAMETER_DOSE_NOT_EXIST"}, status=400)
movies = Movie.objects.filter(country__name="한국").order_by('-release_date')
if country_name == "외국":
movies = Movie.objects.exclude(country__name="한국").filter(country__name__isnull = False).distinct().order_by('-release_date')
if genre1 and genre2:
movies = Movie.objects.filter(genre__name=genre1 and genre2, genre__name__isnull = False).order_by('-release_date').distinct()
if rating:
movies = Movie.objects.order_by('-average_rating').filter(country__name__isnull = False)
movie_list = [{
"country_name" : [country.name for country in movie.country.all()],
"movie_name" : movie.title,
"released_date" : movie.release_date,
"average_rating" : movie.average_rating,
"poster_image" : movie.poster_image
} for movie in movies ][OFFSET : LIMIT]
return JsonResponse({"MOVIE_LIST" : movie_list}, status=200)
+추가) 뒤늦게 발견한 근본 원인
null 값을 가진 영화들이 불러와지는 근본 문제는 movies 테이블에 같은 영화가 중복으로 들어가있어, 그 중복으로 들어간 영화들이 movie_countries라는 중간테이블에 country와 짝지어 들어가지 않았기 때문이었습니다.^^
DB를 다시 정리하면서, 코드 리팩토링을 하였고, 아래 코드와 같은 결과물을 얻게 되었습니다.
👇 최종 결과물
class MovieView(View):
def get(self,request):
country_name = request.GET.get("country")
genre1 = request.GET.get("genre1")
genre2 = request.GET.get("genre2")
rating = request.GET.get("rating","")
KOREAN_MOVIE = "한국"
FOREIGN_MOVIE = "외국"
LIMIT = 25
OFFSET = 0
q = Q()
if country_name == KOREAN_MOVIE:
q.add(Q(country__name=KOREAN_MOVIE), q.AND)
if country_name == FOREIGN_MOVIE:
q.add(~Q(country__name=KOREAN_MOVIE), q.AND)
movies = Movie.objects.filter(q).order_by('-release_date').distinct()
if rating:
movies = Movie.objects.order_by('-average_rating')
movie_list = [{
"country_name" : [country.name for country in movie.country.all()],
"movie_name" : movie.title,
"movie_id" : movie.id,
"released_date" : movie.release_date,
"average_rating" : movie.average_rating,
"poster_image" : movie.poster_image
} for movie in movies ][OFFSET : LIMIT]
return JsonResponse({"MOVIE_LIST" : movie_list}, status=200)