220519 Today I learned!
- 1학기 마지막 프로젝트
1. Fact
(1) 1학기 마지막 프로젝트
- 트레일러 페이지 API
- profile_imge 필드 수정
- 회원 가입 시 기입한 정보가 DB에 저장되지 않는 오류를 수정했다.
- MovieReview API
- 최신순, 인기순 필터
- CRUD
- 프로필 페이지, 회원정보 수정 API
- 영화 추천 API
- 최근 개봉 인기 영화 (50일 이내 개봉, 인기도 순으로 정렬)
- 요즘 제일 관심 받는 영화 (30일내에 작성된 리뷰가 많은 영화)
- 계절 추천 영화 (계절별 특정의 인기 있는 영화를 추천)
- Vue 초기 셋팅
- 프로젝트 깃허브
- 프로젝트 노션
2. Feeling
어제 구현하지 못한 회원 탈퇴를 구현했다. settings.py
의 installed app에 빠진 내역이 있어서 오류가 발생했던 것이다 ㅠㅠ 요즘 왜맞틀~을 왜치면서 오류를 찾는 데 바쁘다. 그래도 오늘 백엔드는 끝이났고 내일부터 프론트 엔드를 시작할 것 같다. 과연 내가 기획했던 것들을 전부 구현할 수 있을지 모르겠지만,,,,
Vue에 대한 실력이 미숙한 것은 누구보다 알지만 프로젝트를 하면서 많이 배워갈 수 있을 거라는 생각이 든다.
3. Finding
django orm은 신이다….
- annotate로 생성한 열을 filter로 조건을 줄 수 있다. 또한,
__
를 활용하면 역참조 모델의 다른 필드에 접근할 수 있다.
1
2
3
4
5
6
7
8
now = timezone.now()
movies = Movie.objects.annotate(
review_count=Count(
'review', distinct=True, filter = Q(
review__created_at__range=[now-timedelta(days=30), now]
))).order_by('-review_count')[:21]
serializer = MovieListSerializer(movies, many=True)
return Response(serializer.data)
annotate를 통해 review_count column을 생성하고 생성한 열을 created_at 범위로 filter설정을 준다.
그 결과, 30일 이내 reivew를 작성한 수가 많은 영화에 대한 데이터를 받아올 수 있다.
order_by('?')
는 랜덤으로 정렬한 결과를 도출한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
now = int(timezone.now().strftime('%m'))
if now == 3 or now == 4 or now == 5:
season = 'spring'
elif now == 6 or now == 7 or now == 8:
season = 'summer'
elif now == 9 or now == 10 or now == 12:
season = 'fall'
else:
season = 'winter'
season_code = {
'spring': 10749, 'summer': 27, 'fall': 12, 'winter': 14
}
genre_id = season_code.get(season)
movies = Movie.objects.filter(genre_ids=genre_id, popularity__gt=99).order_by('?')[:21]
serializer = MovieListSerializer(movies, many=True)
return Response(serializer.data)
너무 인기도로만 정렬 하면 겹치는 추천영화가 많을 것을 예상했다. 그래서 인기도의 하한선을 정한뒤, 랜덤으로 정렬하여 데이터를 보낸다.
~Q()
은 not~과 같다.
1
2
3
movie = Movie.objects.filter(~Q(trailer_youtube_key='nothing') ,popularity__gt=99).order_by('?')
serializer = MovieTrailerSerializer(movie, many=True)
return Response(serializer.data)
~Q(trailer_youtube_key='nothing'
=> trailer_youtube_key가 있는 경우를 의미한다. (데이터를 받을 때 조건에 맞는 데이터가 없으면 ‘nothing’를 저장하기 때문이다.)
즉, trailer_youtube_key가 있고 인기도가 99를 넘는 영화를 랜덤으로 정렬한다.
URL을 조심하자…!
/api/v1/accounts/login, signup이 되지 않아 골치가 많이 아팠다. 갑자기 자격 인증데이터(authentication credentials)가 제공되지 않아서 접근할 수 었다는 오류가 발생했다. login과 signup단계에서는 당연히 토근이 생성되지 않았기 때문에 토큰을 가져올 수 없는데, 왜 이럴까 고민했다.
그런데! 나의 빛과 소금과 같은 프엔 스터디 친구들이 도움을 주었다.
1
2
3
4
5
6
7
8
9
10
11
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/movie/', include('movies.urls')),
path('api/v1/article/', include('articles.urls')),
path('api/v1/accounts/', include('dj_rest_auth.urls')),
path('api/v1/accounts/signup/', include('dj_rest_auth.registration.urls')),
# 프로필로 가는 url 뒤에 <str:username>이 붙을 예정이다.
path('api/v1/accounts/', include('accounts.urls')),
]
여기서 중요한 것은 path('api/v1/accounts/', include('accounts.urls'))
를 가장 맨뒤로 보내야 한다는 것이다.
만약 상단에 배치한다면, 해당 url은 뒤에 <str:username>
이 붙기 때문에 api/v1/accounts/login 혹은 api/v1/accounts/signip/의 뒷부분이 문자열로 인식된다.
그 결과, 내가 생각했던 view함수가 실행되지 않을 것이다. 또한, 위의 url의 문제점은 signup이라는 아이디를 가진 사람은 자신의 프로필 페이지에 절대 가지 못한다. 😅 그래서 결국 api/v1/accounts/profile/<str:username>
으로 수정했다.
4. Future Action & Feedback
Future Action | 진행 상황 | Feedback |
---|---|---|
DOM을 깨우치다 | pause 🤦♀️ | 잠시 중단! |
why 리액트? | Not Start🌙 |