Skip to content
Snippets Groups Projects
Commit 1da1adb3 authored by Tobias Ørstad's avatar Tobias Ørstad
Browse files

Fix workouts code smells

parent 108932ba
No related branches found
No related tags found
2 merge requests!31Complete exercise 3,!27Backendsecfitsmells
Pipeline #127087 passed
...@@ -153,13 +153,10 @@ class RememberMe(models.Model): ...@@ -153,13 +153,10 @@ class RememberMe(models.Model):
return self.remember_me return self.remember_me
# Likes for a workout
class WorkoutLike(models.Model): class WorkoutLike(models.Model):
# The workout that is being liked
workoutToLike = models.ForeignKey(Workout, on_delete=models.CASCADE) workoutToLike = models.ForeignKey(Workout, on_delete=models.CASCADE)
# The user doing the liking
userLiking = models.ForeignKey( userLiking = models.ForeignKey(
get_user_model(), on_delete=models.CASCADE, related_name="userLiking" get_user_model(), on_delete=models.CASCADE, related_name="userLiking"
) )
\ No newline at end of file
...@@ -165,27 +165,31 @@ class WorkoutSerializer(serializers.HyperlinkedModelSerializer): ...@@ -165,27 +165,31 @@ class WorkoutSerializer(serializers.HyperlinkedModelSerializer):
# Handle WorkoutFiles # Handle WorkoutFiles
if "files" in validated_data: if "files" in validated_data:
files_data = validated_data.pop("files") self.handleFiles(instance,validated_data)
files = instance.files
for file, file_data in zip(files.all(), files_data):
file.file = file_data.get("file", file.file)
# If new files have been added, creating new WorkoutFiles
if len(files_data) > len(files.all()):
for i in range(len(files.all()), len(files_data)):
WorkoutFile.objects.create(
workout=instance,
owner=instance.owner,
file=files_data[i].get("file"),
)
# Else if files have been removed, delete WorkoutFiles
elif len(files_data) < len(files.all()):
for i in range(len(files_data), len(files.all())):
files.all()[i].delete()
return instance return instance
def handleFiles(self, instance, validated_data):
files_data = validated_data.pop("files")
files = instance.files
for file, file_data in zip(files.all(), files_data):
file.file = file_data.get("file", file.file)
# If new files have been added, creating new WorkoutFiles
if len(files_data) > len(files.all()):
for i in range(len(files.all()), len(files_data)):
WorkoutFile.objects.create(
workout=instance,
owner=instance.owner,
file=files_data[i].get("file"),
)
# Else if files have been removed, delete WorkoutFiles
elif len(files_data) < len(files.all()):
for i in range(len(files_data), len(files.all())):
files.all()[i].delete()
def get_owner_username(self, obj): def get_owner_username(self, obj):
"""Returns the owning user's username """Returns the owning user's username
......
"""Contains views for the workouts application. These are mostly class-based views. """Contains views for the workouts application. These are mostly class-based views.
""" """
from rest_framework import generics, mixins from rest_framework import generics, mixins, permissions, status, filters
from rest_framework import permissions
from rest_framework.parsers import ( from rest_framework.parsers import (
JSONParser, JSONParser,
) )
import json import json
from rest_framework import status
from rest_framework.decorators import api_view from rest_framework.decorators import api_view
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.reverse import reverse from rest_framework.reverse import reverse
from django.db.models import Q, Sum, F, IntegerField from django.db.models import Q, Sum, F, IntegerField
from rest_framework import filters
from workouts.parsers import MultipartJsonParser from workouts.parsers import MultipartJsonParser
from workouts.permissions import ( from workouts.permissions import (
IsOwner, IsOwner,
...@@ -25,17 +21,12 @@ from workouts.permissions import ( ...@@ -25,17 +21,12 @@ from workouts.permissions import (
) )
from workouts.mixins import CreateListModelMixin from workouts.mixins import CreateListModelMixin
from workouts.models import Workout, Exercise, ExerciseInstance, WorkoutFile, WorkoutLike from workouts.models import Workout, Exercise, ExerciseInstance, WorkoutFile, WorkoutLike
from workouts.serializers import WorkoutSerializer, ExerciseSerializer from workouts.serializers import WorkoutSerializer, ExerciseSerializer, RememberMeSerializer, ExerciseInstanceSerializer, WorkoutFileSerializer
from workouts.serializers import RememberMeSerializer
from workouts.serializers import ExerciseInstanceSerializer, WorkoutFileSerializer
from django.core.exceptions import PermissionDenied from django.core.exceptions import PermissionDenied
from rest_framework_simplejwt.tokens import RefreshToken from rest_framework_simplejwt.tokens import RefreshToken
from rest_framework.response import Response
import json
from collections import namedtuple from collections import namedtuple
import base64, pickle import base64, pickle
from django.core.signing import Signer from django.core.signing import Signer
from users.models import User from users.models import User
from rest_framework.views import APIView from rest_framework.views import APIView
...@@ -76,10 +67,10 @@ class RememberMe( ...@@ -76,10 +67,10 @@ class RememberMe(
return Response({"remember_me": self.rememberme()}) return Response({"remember_me": self.rememberme()})
def post(self, request): def post(self, request):
cookieObject = namedtuple("Cookies", request.COOKIES.keys())( cookie_object = namedtuple("Cookies", request.COOKIES.keys())(
*request.COOKIES.values() *request.COOKIES.values()
) )
user = self.get_user(cookieObject) user = self.get_user(cookie_object)
refresh = RefreshToken.for_user(user) refresh = RefreshToken.for_user(user)
return Response( return Response(
{ {
...@@ -88,8 +79,8 @@ class RememberMe( ...@@ -88,8 +79,8 @@ class RememberMe(
} }
) )
def get_user(self, cookieObject): def get_user(self, cookie_object):
decode = base64.b64decode(cookieObject.remember_me) decode = base64.b64decode(cookie_object.remember_me)
user, sign = pickle.loads(decode) user, sign = pickle.loads(decode)
# Validate signature # Validate signature
...@@ -237,34 +228,38 @@ class Leaderboards(APIView): ...@@ -237,34 +228,38 @@ class Leaderboards(APIView):
# User must be logged in # User must be logged in
if self.request.user: if self.request.user:
leaderboardNumbers = ExerciseInstance.objects.filter(Q(exercise__pk=pk) & Q(workout__visibility='PU')).values('workout__owner__pk').annotate(amount=Sum(F("sets") * F("number"), output_field=IntegerField())).order_by('-amount') leaderboard_numbers = ExerciseInstance.objects.filter(Q(exercise__pk=pk) & Q(workout__visibility='PU')).values('workout__owner__pk').annotate(amount=Sum(F("sets") * F("number"), output_field=IntegerField())).order_by('-amount')
leaderboard_result = []
leaderboardResult = []
# Iterates through the top 5 entries in the leaderboard and formats it correctly
for i in range(0, min(5, len(leaderboardNumbers))):
leaderboardResult.append({"name": User.objects.get(pk=leaderboardNumbers[i]['workout__owner__pk']).username, "value": leaderboardNumbers[i]['amount']})
# Applies the rank to the leaderboard entry; if two or more users have the score they get the same rank
if i > 0 and leaderboardNumbers[i-1]["amount"] == leaderboardNumbers[i]["amount"]:
leaderboardResult[i]["rank"] = leaderboardResult[i-1]["rank"]
else:
leaderboardResult[i]["rank"] = i+1
# Finds the user in the leaderboard list. If the user is not in the leaderboard list,
# the user is automatically given a score of 0 and the worst rank
currentLoggedInUser = self.request.user self.addtop5(leaderboard_result, leaderboard_numbers)
current_logged_in_user = self.request.user
for j in range(0, len(leaderboardNumbers)): self.adduserscore(current_logged_in_user, leaderboard_result, leaderboard_numbers)
if leaderboardNumbers[j]['workout__owner__pk'] == currentLoggedInUser.pk:
if j+1 > 5: return Response(leaderboard_result)
leaderboardResult.append({"name": currentLoggedInUser.username, "value": leaderboardNumbers[j]["amount"], "rank": j+1})
break def addtop5(self, leaderboard_result, leaderboard_numbers):
# Iterates through the top 5 entries in the leaderboard and formats it correctly
for i in range(0, min(5, len(leaderboard_numbers))):
leaderboard_result.append({"name": User.objects.get(pk=leaderboard_numbers[i]['workout__owner__pk']).username, "value": leaderboard_numbers[i]['amount']})
# Applies the rank to the leaderboard entry; if two or more users have the score they get the same rank
if i > 0 and leaderboard_numbers[i-1]["amount"] == leaderboard_numbers[i]["amount"]:
leaderboard_result[i]["rank"] = leaderboard_result[i-1]["rank"]
else: else:
leaderboardResult.append({"name": currentLoggedInUser.username, "value": 0, "rank": len(leaderboardNumbers) + 1}) leaderboard_result[i]["rank"] = i+1
def adduserscore(self, current_logged_in_user, leaderboard_result, leaderboard_numbers):
# Finds the user in the leaderboard list. If the user is not in the leaderboard list,
# the user is automatically given a score of 0 and the worst rank
return Response(leaderboardResult) for j in range(0, len(leaderboard_numbers)):
if leaderboard_numbers[j]['workout__owner__pk'] == current_logged_in_user.pk:
if j+1 > 5:
leaderboard_result.append({"name": current_logged_in_user.username, "value": leaderboard_numbers[j]["amount"], "rank": j+1})
break
else:
leaderboard_result.append({"name": current_logged_in_user.username, "value": 0, "rank": len(leaderboard_numbers) + 1})
class ExerciseInstanceList( class ExerciseInstanceList(
...@@ -395,25 +390,25 @@ class WorkoutLiking(APIView): ...@@ -395,25 +390,25 @@ class WorkoutLiking(APIView):
# and the workout has not been liked before), and the amount of likes that the workout has # and the workout has not been liked before), and the amount of likes that the workout has
def get(self, request, pk): def get(self, request, pk):
likingAllowed = Workout.objects.get(pk=pk).owner != self.request.user and WorkoutLike.objects.filter( liking_allowed = Workout.objects.get(pk=pk).owner != self.request.user and WorkoutLike.objects.filter(
Q(userLiking=self.request.user) & Q(workoutToLike__pk=pk)).count() == 0 Q(userLiking=self.request.user) & Q(workoutToLike__pk=pk)).count() == 0
likeAmount = WorkoutLike.objects.filter(Q(workoutToLike__pk=pk)).count() + 1 like_amount = WorkoutLike.objects.filter(Q(workoutToLike__pk=pk)).count() + 1
return Response((likingAllowed, likeAmount), status.HTTP_200_OK) return Response((liking_allowed, like_amount), status.HTTP_200_OK)
# Tries to like a new post and returns the same as the GET above # Tries to like a new post and returns the same as the GET above
def post(self, request, pk): def post(self, request, pk):
likingAllowed = Workout.objects.get(pk=pk).owner != self.request.user and WorkoutLike.objects.filter( liking_allowed = Workout.objects.get(pk=pk).owner != self.request.user and WorkoutLike.objects.filter(
Q(userLiking=self.request.user) & Q(workoutToLike__pk=pk)).count() == 0 Q(userLiking=self.request.user) & Q(workoutToLike__pk=pk)).count() == 0
likeAmount = WorkoutLike.objects.filter(Q(workoutToLike__pk=pk)).count() + 1 like_amount = WorkoutLike.objects.filter(Q(workoutToLike__pk=pk)).count() + 1
if likingAllowed: if liking_allowed:
newWorkoutLike = WorkoutLike(workoutToLike=Workout.objects.get(pk=pk), userLiking=self.request.user) new_workout_like = WorkoutLike(workoutToLike=Workout.objects.get(pk=pk), userLiking=self.request.user)
newWorkoutLike.save() new_workout_like.save()
return Response((False, likeAmount + 1), status.HTTP_201_CREATED) return Response((False, like_amount + 1), status.HTTP_201_CREATED)
return Response((likingAllowed, likeAmount), status.HTTP_100_CONTINUE) return Response((liking_allowed, like_amount), status.HTTP_100_CONTINUE)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment