프립은 웹사이트와 애플리케이션을 통해 액티비티, 원데이 클래스, 소셜클럽, 여행 상품 등을 탐색부터 결제, 참여까지 간편하게 이용할 수 있는 서비스를 제공하고 있습니다.
팀원구성 : 프론트 2명, 백엔드 3명
팀명 : 드립 - 모바일버전
User app
Review app
Product app
Order app
이번에는 팀원분들이 많이 양보해줘서 api 2개를 이용할 수 있게 되었고, 리뷰쪽이랑, 소셜로그인을 구현하게 되었습니다.
class KakaoSigninView(View):
def post(self, request):
try:
access_token = request.headers.get("Authorization")
if not access_token:
return JsonResponse({'message' : 'ACCESS_TOKEN_DOES_NOT_EXITS'}, status=401)
headers = ({'Authorization':f'Bearer {access_token}'})
kakao_url = 'https://kapi.kakao.com/v2/user/me'
response = requests.get(kakao_url, headers = headers)
user = response.json()
if not user:
return JsonResponse({'message' : 'INVALID_TOKEN'}, status=401)
user, created = User.objects.get_or_create(
name = user['kakao_account']['profile'].get('nickname'),
email = user['kakao_account'].get('email'),
profile_image = user['kakao_account']['profile'].get('profile_image_url'),
origin_pk = user.get('id')
)
result = {
'name' : user.name,
'profile_image' : user.profile_image,
'email' : user.email
}
token = jwt.encode({'id' : user.id}, SECRET_KEY, ALGORITHM)
return JsonResponse({'token' : token, 'data' : result}, status = 201)
except IntegrityError:
return JsonResponse({'message' : 'INTEGRITY_ERROR'}, status=401)
except KeyError:
return JsonResponse({'message' : 'KEY_ERROR'}, status=400)
class ReviewView(View):
@login_decorator
def post(self, request):
try:
user = request.user
content = request.POST['content']
rating = request.POST['rating']
product = Product.objects.get(id=request.POST['product'])
s3_client = boto3.client(
's3',
aws_access_key_id = ACCESS_KEY,
aws_secret_access_key = SECRET_ACCESS_KEY
)
image = request.FILES['filename']
image_time = (str(datetime.now())).replace(" ","")
image_type = (image.content_type).split("/")[1]
s3_client.upload_fileobj(
image,
"dripawsbucket21",
image_time+"."+image_type,
ExtraArgs = {
"ContentType" : image.content_type
}
)
image_url = "https://dripawsbucket21.s3.ap-northeast-2.amazonaws.com/"+image_time+"."+image_type
Review.objects.create(
user = user,
content = content,
rating = rating,
image_url = image_url if image else None,
product = product,
)
return JsonResponse({'result' : 'SUCCESS'}, status = 201)
except KeyError:
return JsonResponse({'message' : 'KEY_ERROR'}, status = 400)
@login_decorator
def get(self, request, product_id):
try:
user = request.user
order = request.GET.get('order')
order_conditions = {
'new' : '-created_at',
'old' : 'created_at',
'like' : '-like_count',
'unlike' : 'like_count',
}
reviews = Review.objects.filter(product_id=product_id).annotate(like_count = Count('like')).order_by(order_conditions.get(order, '-created_at'))
review_list = [{
'created_at' : review.created_at,
'user' : review.user.name,
'content' : review.content,
'rating' : review.rating,
'product' : product_id,
'like_count' : review.like_set.count(),
'review_count' : reviews.count(),
'image_url' : review.image_url,
'like' : Like.objects.filter(user_id = user.id, review_id = review.id).exists(),
'user_image' : review.user.profile_image,
'avgrating' : reviews.aggregate(avgrating=Avg('rating'))
} for review in reviews]
return JsonResponse({'result' : review_list, 'avgrating' : reviews.aggregate(avgrating=Avg('rating'))['avgrating']}, status = 200)
except Product.DoesNotExist:
return JsonResponse({"message" : 'DOES_NOT_EXIT_PRODUCT_ID'}, status = 401)
class CommentView(View):
@login_decorator
def post(self, request):
try:
data = json.loads(request.body)
content = data['content']
user = request.user
review = Review.objects.get(id=data['review'])
Comment.objects.create(
user = user,
content = content,
review = review
)
return JsonResponse({'message' : 'SUCCESS'}, status = 201)
except KeyError:
return JsonResponse({'message' : 'KEY_ERROR'}, status = 400)
@login_decorator
def get(self, review_id):
try:
comment_list = [{
'user' : comment_list.user.id,
'content' : comment_list.content,
'review' : review_id
}for comment_list in Comment.objects.filter(review_id = review_id)]
return JsonResponse({'result' : comment_list}, status = 200)
except Review.DoesNotExist:
return JsonResponse({"message" : 'DOES_NOT_EXIT_REVIEW_ID'}, status = 401)
class LikeView(View):
@login_decorator
def post(self, request):
try:
data = json.loads(request.body)
user = request.user
review_id = data['review_id']
if not Review.objects.filter(id = review_id).exists():
return JsonResponse({'message' : 'INVALID_REVIEW'}, status = 401)
if not Like.objects.filter(user = user, review_id = review_id).exists():
Like.objects.create(user = user, review_id = review_id)
return JsonResponse({'message' : 'SUCCESS'}, status= 201)
except KeyError:
return JsonResponse({'message' : 'KEY_ERROR'}, status = 400)
@login_decorator
def delete(self, request, review_id):
Like.objects.filter(user = request.user, review_id = review_id).delete()
return JsonResponse({'message' : 'SUCCESS'},status = 204)
이번 2차 프로젝트는 노션을 통해서 key값, body값, path등을 공유하게 되었고, 기능 구현하느라 늦게 작성할 때가 많았지만 프론트분들이 많이 이해해주셔서 원활하게 진행할 수 있었던 것 같습니다. 감사합니다!!
한마디로 말하면 처음부터 쫄지말고, 도전하면 어떻게든 진행할 수 있다는 것입니다. 저를 돌아보면 프로젝트 진행하기 전에는 실력이 많이 부족하다고 생각해서 어떻게 하지…. 라는 생각을 많이 했습니다. 그렇지만 1차 프로젝트를 진행하면서 서서히 자신감이 생겼고 2차를 진행하면서 2주 동안 2개의 API를 이용했고, unit 테스트 까지 마칠 수 있었던 것 같습니다. 처음에는 불가능할 것 같았지만, 포기만 하지 않으면 할 수 있다는 점을 배우게 되는 계기였습니다. 항상 패기있는 백엔드 개발자가 되도록 항상 도전하는 자세를 가지겠습니다.💡