nabilah_argyanti_ardyningrum/backend/easycookapi-main/profiles/views.py
2024-12-31 09:49:01 +07:00

302 lines
12 KiB
Python

from .models import Information
from django.contrib.auth.models import User
from rest_framework import generics, status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from django.db.models import Count, Max
from .models import Account, Pantry, History, Favorite
from .serializers import (
AccountSerializer, FavoriteSerializer, HistorySerializer, PantrySerializer, ProfilePictureSerializer
)
from recipes.models import Information, RawIngredient
from recipes.serializers import RecipeInformationSerializer, RawIngredientSerializer
from .utils import calculate_top_recipes_by_ingredients, get_hybrid_recommendation, get_recommendations_for_user
class AccountView(generics.GenericAPIView):
permission_classes = [IsAuthenticated]
serializer_class = AccountSerializer
def get(self, request):
account = Account.objects.get(user_id=request.user.id)
serializer = self.get_serializer(account)
return Response(serializer.data)
def post(self, request):
account = User.objects.get(id=request.user.id)
account_serializer = self.get_serializer(
instance=account, data=request.data)
profile_picture_serializer = ProfilePictureSerializer(
instance=account.account, data=request.data)
if profile_picture_serializer.is_valid(raise_exception=True):
profile_picture_serializer.save()
if account_serializer.is_valid(raise_exception=True):
account_serializer.save()
return Response(account_serializer.data)
class FavoriteView(generics.GenericAPIView):
permission_classes = [IsAuthenticated]
def get(self, request):
user = request.user
recipes = Information.objects.filter(
favorite__user=user).order_by("-favorite__created_at")
recipes_serializer = RecipeInformationSerializer(
recipes, context={'request': request}, many=True)
return Response(recipes_serializer.data)
def post(self, request, recipe_id):
user = request.user
try:
recipe = Information.objects.get(id=recipe_id)
except Information.DoesNotExist:
return Response({'message': 'Resep tidak ditemukan'}, status=status.HTTP_404_NOT_FOUND)
source = request.data.get('source', '')
favorite, created = Favorite.objects.get_or_create(
user=user, recipe=recipe, source=source)
if created:
favorite_serializer = FavoriteSerializer(
favorite, context={'request': request})
return Response(favorite_serializer.data, status=status.HTTP_201_CREATED)
else:
return Response({'message': 'Anda sudah menambahkan resep ini ke favorit'}, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, recipe_id):
favorite = Favorite.objects.filter(
recipe_id=recipe_id, user=request.user).first()
if favorite:
favorite.delete()
return Response({'message': 'Berhasil menghapus resep dari daftar favorit'}, status=status.HTTP_200_OK)
else:
return Response({'message': 'Data tidak ditemukan'}, status=status.HTTP_404_NOT_FOUND)
class HistoryView(generics.GenericAPIView):
def get(self, request):
user = request.user
recipes = Information.objects.filter(history__user=user).annotate(
newest_created_at=Max('history__created_at')).order_by('-newest_created_at')
recipes_serializer = RecipeInformationSerializer(
recipes, context={'request': request}, many=True)
return Response(recipes_serializer.data)
def post(self, request, recipe_id):
if request.user.is_authenticated:
user = request.user
else:
user = User.objects.get(id=4)
try:
recipe = Information.objects.get(id=recipe_id)
except Information.DoesNotExist:
return Response({'message': 'Resep tidak ditemukan'}, status=status.HTTP_404_NOT_FOUND)
source = request.data.get('source', '')
history = History(
user=user, recipe=recipe, source=source)
history.save()
history_serializer = HistorySerializer(history)
return Response(history_serializer.data, status=status.HTTP_201_CREATED)
def delete(self, request, recipe_id):
history = History.objects.filter(
recipe_id=recipe_id, user=request.user).first()
if history:
history.delete()
return Response({'message': 'History berhasil dihapus'}, status=status.HTTP_200_OK)
else:
return Response({'message': 'History tidak ditemukan'}, status=status.HTTP_404_NOT_FOUND)
class PantryView(generics.GenericAPIView):
permission_classes = [IsAuthenticated]
serializer_class = PantrySerializer
def get(self, request):
pantry = Pantry.objects.filter(user=request.user)
if pantry.exists():
serializer = PantrySerializer(pantry, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
else:
return Response({"message": "Penyimpanan kosong."}, status=status.HTTP_204_NO_CONTENT)
def post(self, request):
user = request.user
raw_ingredient_id = request.data.get('id')
amount = request.data.get('amount')
unit_id = request.data.get('unit_id')
raw_ingredient_ids = request.data.get('raw_ingredient_id', [])
if (len(raw_ingredient_ids) != 0):
Pantry.objects.filter(user=user).delete()
raw_ingredients = RawIngredient.objects.filter(
pk__in=raw_ingredient_ids)
for raw_ingredient in raw_ingredients:
pantry = Pantry(user=user, raw_ingredient=raw_ingredient)
pantry.save()
user = request.user
top_recipes = calculate_top_recipes_by_ingredients(user)[:12]
top_recipe_ids = [recipe['recipe_id'] for recipe in top_recipes]
recipes = Information.objects.filter(id__in=top_recipe_ids).annotate()
recipes_list = RecipeInformationSerializer(
recipes, context={'request': request, 'top_recipes': top_recipes}, many=True).data
sorted_recipes = sorted(
recipes_list,
key=lambda x: (0.8 * next(
(item['similarity'] for item in top_recipes if item['recipe_id'] == x['id']), 0)) +
(0.2 * x['completeness_percentage']),
reverse=True
)
return Response(sorted_recipes, status=status.HTTP_200_OK)
else:
try:
pantry = Pantry.objects.get(
user=user, raw_ingredient_id=raw_ingredient_id)
pantry.amount = amount
pantry.unit_id = unit_id
pantry.save()
pantry_serializer = PantrySerializer(pantry).data
return Response(pantry_serializer, status=status.HTTP_200_OK)
except Pantry.DoesNotExist:
pantry = Pantry.objects.create(
user=user, raw_ingredient_id=raw_ingredient_id, amount=amount, unit_id=unit_id)
pantry_serializer = PantrySerializer(pantry).data
return Response(pantry_serializer, status=status.HTTP_200_OK)
def delete(self, request, pantry_id):
pantry = Pantry.objects.filter(
user=request.user, id=pantry_id)
pantry.delete()
return Response('Berhasil menghapus data', status=status.HTTP_204_NO_CONTENT)
class UpdatePasswordView(generics.GenericAPIView):
permission_classes = [IsAuthenticated]
def post(self, request):
user = request.user
current_password = request.data.get('current_password')
new_password = request.data.get('new_password')
if user.check_password(current_password):
user.set_password(new_password)
user.save()
return Response("Password berhasil diperbarui", status=status.HTTP_200_OK)
else:
return Response("Password saat ini salah", status=status.HTTP_400_BAD_REQUEST)
class PantryRecommendationView(generics.GenericAPIView):
permission_classes = [IsAuthenticated]
def get(self, request):
user = request.user
top_recipes = calculate_top_recipes_by_ingredients(user)[:20]
top_recipe_ids = [recipe['recipe_id'] for recipe in top_recipes]
recipes = Information.objects.filter(id__in=top_recipe_ids).annotate()
recipes_list = RecipeInformationSerializer(
recipes, context={'request': request, 'top_recipes': top_recipes}, many=True).data
filtered_recipes = [
recipe for recipe in recipes_list if recipe['completeness_percentage'] > 0]
sorted_recipes = sorted(
filtered_recipes,
key=lambda x: (0.8 * next(
(item['similarity'] for item in top_recipes if item['recipe_id'] == x['id']), 0)) +
(0.2 * x['completeness_percentage']),
reverse=True
)
sorted_recipes = sorted_recipes[:12]
return Response(sorted_recipes, status=status.HTTP_200_OK)
class CFRecommendationView(generics.GenericAPIView):
permission_classes = [IsAuthenticated]
serializer_class = RecipeInformationSerializer
def get(self, request):
user_id = self.request.user.id
top_recipes = get_recommendations_for_user(user_id)[:20]
top_recipes_ids = [recipe['recipe_id']
for recipe in top_recipes]
recipes = Information.objects.filter(
id__in=top_recipes_ids)
recipes_list = RecipeInformationSerializer(
recipes, context={'request': request, 'top_recipes': top_recipes}, many=True).data
sorted_recipes = sorted(
recipes_list, key=lambda x: x['similarity'], reverse=True)
return Response(sorted_recipes, status=status.HTTP_200_OK)
class MostViewedRecommendationView(generics.GenericAPIView):
def get(self, request):
recipe_counts = History.objects.values('recipe_id').annotate(
count=Count('recipe_id')).order_by('-count')[:9]
recipe_ids = [count['recipe_id'] for count in recipe_counts]
recipes = Information.objects.filter(
id__in=recipe_ids).annotate(history_count=Count('history')).order_by('-history_count')
recipes_list = RecipeInformationSerializer(
recipes, context={'request': request}, many=True).data
return Response(recipes_list, status=status.HTTP_200_OK)
class FavoriteRecommendationView(generics.GenericAPIView):
def get(self, request):
recipe_counts = Favorite.objects.values('recipe_id').annotate(
count=Count('recipe_id')).order_by('-count')[:9]
recipe_ids = [count['recipe_id'] for count in recipe_counts]
recipes = Information.objects.filter(
id__in=recipe_ids).annotate(favorite_count=Count('favorite')).order_by('-favorite_count')
recipes_list = RecipeInformationSerializer(
recipes, context={'request': request}, many=True).data
return Response(recipes_list, status=status.HTTP_200_OK)
# Unused
class HybridRecommendationView(generics.GenericAPIView):
permission_classes = [IsAuthenticated]
serializer_class = RecipeInformationSerializer
def get(self, request):
user_id = self.request.user.id
recommended_recipe_ids = get_hybrid_recommendation(user_id)[:9]
recipes = Information.objects.filter(id__in=recommended_recipe_ids)
recipes_list = RecipeInformationSerializer(
recipes, context={'request': request}, many=True).data
sorted_recipes = sorted(
recipes_list, key=lambda x: x['completeness_percentage'], reverse=True)[:9]
return Response(sorted_recipes, status=status.HTTP_200_OK)