def post(self, request, format=None): """Adds new exercise for specic user.""" serializer = ExerciseSerializer(data={**request.data, "owner": request.user.pk}) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_201_CREATED) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def test_fork_routine(self): """Fork other user's routine when this is permitted (no name collision).""" routine_to_fork = Routine.objects.get(owner=self.other_user.pk, name="Routine to fork") # Grab exercise that should be a part of new routine but should not be recreated owner_exercise = Exercise.objects.get(owner=self.owner, name="Same name exercise") owner_exercise_data_before = ExerciseSerializer(owner_exercise).data url = reverse(self.DETAIL_URLPATTERN_NAME, kwargs={"routine_id": routine_to_fork.pk}) response = self.client.post(url) self.assertEqual(response.status_code, status.HTTP_201_CREATED) routine_to_fork.refresh_from_db() routine_forked = Routine.objects.get(owner=self.owner, name=routine_to_fork.name) # Test forking logic self.assertEqual(routine_forked.forks_count, 0, msg="forked routine should have 0 forks") self.assertEqual(routine_to_fork.forks_count, 11, msg="original routine should have new fork") self.assertEqual(routine_forked.kind, routine_to_fork.kind) self.assertEqual(routine_forked.instructions, routine_to_fork.instructions) serializer = RoutineUnitSerializer(routine_forked.routine_units.all(), many=True) exercise_names = [ "Other exercise 1", "Other exercise 2", "Other exercise 3", "Other exercise 4", "Other exercise 5", "Same name exercise", ] for exercise_name, routine_unit_dict in zip(exercise_names, serializer.data): self.assertEqual(routine_unit_dict["exercise_name"], exercise_name) self.assertEqual(routine_unit_dict["sets"], 10) self.assertEqual(routine_unit_dict["instructions"], "fork me") # Ensure forked rouine contains original owner exercise self.assertEqual(serializer.data[-1]["exercise"], owner_exercise_data_before["pk"]) # Ensure owner "Same name exercise" exercise was not modified owner_exercise.refresh_from_db() owner_exercise_data_after = ExerciseSerializer(owner_exercise).data self.assertEqual(owner_exercise_data_before, owner_exercise_data_after)
def put(self, request, exercise_id, format=None): """Edit exercise data. This can be done only if the user requesting edot is an exercise owner.""" exercise = self.get_object(exercise_id) if request.user == exercise.owner: serializer = ExerciseSerializer( exercise, data={**request.data, "owner": request.user.pk} ) if serializer.is_valid(): serializer.save() return Response(serializer.data, status=status.HTTP_200_OK) return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) return Response(status=status.HTTP_403_FORBIDDEN)
def post(self, request, exercise_id, format=None): """Fork (copy) exercise. This operation creates new exercise with all internal values copied but new owner. New owner is the author of the request. If fork is successful updated instance of forked exercise is send in response payload. If fork is unsuccessful dict with errors is send in response payload. """ exercise = self.get_object(exercise_id) # Detect name collision if Exercise.objects.filter(owner=request.user, name=exercise.name).count(): return Response( {"non_field_errors": "You already own an exercise with this name"}, status=status.HTTP_403_FORBIDDEN, ) # Create a copy exercise.fork(request.user) # Increase forks count exercise = self.get_object(exercise_id) exercise.forks_count += 1 exercise.save() serializer = ExerciseSerializer(exercise, context={"user_id": request.user.pk}) return Response(serializer.data, status=status.HTTP_201_CREATED)
class TrainingProgramCreateSerializer(serializers.ModelSerializer): exercises = ExerciseSerializer(many=True) class Meta: model = models.TrainingProgram fields = ('title', 'description', 'exercises') def create(self, validated_data): user = self.context['request'].user exercises = validated_data.pop('exercises', []) training = models.TrainingProgram.objects.create(**validated_data) exercise_objs = [ models.Exercise.objects.create(**exercise, user=user) for exercise in exercises ] training.exercises.add(*exercise_objs) return training def update(self, instance, validated_data): exercises = validated_data.pop('exercises', []) instance = update_instance(instance, validated_data) exercises_obj = models.Exercise.objects.filter( id__in=[e.get('id') for e in exercises]) for obj in exercises_obj: exercise = get_exercise(exercises, obj.id) update_instance(obj, exercise) return instance
def get(self, request, format=None): """Return a list of all exercises. Querystring params: ?user.eq=<int>: Exercises for user with specific pk. ?user.neq=<int>: Exercises that can be discovered by user with specific pk (exercises which are not owned by user with this pk). ?orderby=<str>: Name of db column to order queryset. Default order is given by pk values. Django convention is used – the negative sign in front of column name indicates descending order. ?limit=<int>: Limit querysearch to specific number of records. """ user_pk_filter = request.query_params.get("user.eq", None) user_pk_exclude = request.query_params.get("user.neq", None) order_by_field = request.query_params.get("orderby", None) limit = request.query_params.get("limit", None) # Validation if user_pk_filter is not None and not user_pk_filter.isdigit(): return Response(status=status.HTTP_400_BAD_REQUEST) if user_pk_exclude is not None and not user_pk_exclude.isdigit(): return Response(status=status.HTTP_400_BAD_REQUEST) if limit is not None and not limit.isdigit(): return Response(status=status.HTTP_400_BAD_REQUEST) if order_by_field is not None and order_by_field not in ORDER_BY_OPTIONS: return Response(status=status.HTTP_400_BAD_REQUEST) queryset = Exercise.objects.all() if user_pk_filter: queryset = queryset.filter(owner=user_pk_filter) if user_pk_exclude: queryset = queryset.exclude(owner=user_pk_exclude) if order_by_field: queryset = queryset.order_by(order_by_field) if limit: queryset = queryset[: int(limit)] serializer = ExerciseSerializer( queryset, context={"requesting_user_pk": request.user.pk}, many=True ) return Response(serializer.data, status=status.HTTP_200_OK)
def get(self, request, exercise_id, format=None): """Get information about specific exercise.""" exercise = self.get_object(exercise_id) serializer = ExerciseSerializer(exercise, context={"requesting_user_pk": request.user.pk}) return Response(serializer.data, status=status.HTTP_200_OK)
class TrainingProgramListSerializer(serializers.ModelSerializer): exercises = ExerciseSerializer(many=True) class Meta: model = models.TrainingProgram fields = ('id', 'title', 'description', 'exercises')
class TestSheetSerializer(serializers.ModelSerializer): exercise = ExerciseSerializer(many=True, read_only=False) tutorial = TutorialSerializer(many=True, read_only=False) def create(self, validated_data): tutorial_data = validated_data.pop('tutorial') exercise_data = validated_data.pop('exercise') test_sheet = TestSheetModel.objects.create( author_id=validated_data['author'].id, classroom_id=validated_data['classroom'].id, **validated_data) for t in tutorial_data: TutorialModel.objects.create(test_sheet_id=test_sheet.id, **t) for e in exercise_data: question_data = e.pop('questions') exercise = ExerciseModel.objects.create( test_sheet_id=test_sheet.id, **e) for q in question_data: answer_data = q.pop('answer') question = QuestionModel.objects.create( exercise_id=exercise.id, **q) for a in answer_data: AnswerModel.objects.create(question_id=question.id, **a) return test_sheet def update(self, instance, validated_data): tutorials_data = validated_data.pop('tutorial') exercises_data = validated_data.pop('exercise') instance.author_id = validated_data.get('author_id', instance.author_id) instance.classroom_id = validated_data.get('classroom_id', instance.classroom_id) instance.name = validated_data.get('name', instance.name) instance.difficulty = validated_data.get('difficulty', instance.difficulty) instance.save() for tutorial_data in tutorials_data: tutorial = TutorialModel.objects.filter(id=tutorial_data['id']) tutorial.update(**tutorial_data) for exercise_data in exercises_data: questions_data = exercise_data.pop('questions') exercise = ExerciseModel.objects.filter(id=exercise_data['id']) exercise.update(**exercise_data) for question_data in questions_data: answers_data = question_data.pop('answer') question = QuestionModel.objects.filter(id=question_data['id']) question.update(**question_data) for answer_data in answers_data: answer = AnswerModel.objects.filter(id=answer_data['id']) answer.update(**answer_data) return instance class Meta: model = TestSheetModel fields = [ 'id', 'name', 'author', 'classroom', 'difficulty', 'tutorial', 'exercise' ]
def generate_post_test(request): exercise_instance = None try: session = extract_json_data(request) questions = [] selected_questions = [] query_set_exercises = SessionExercise.objects.filter( session=session["uuid"]).values_list("exercise", flat=True) for item in query_set_exercises: query_set_record_questions = ExerciseQuestion.objects.filter( exercise=item) for qs in query_set_record_questions: questions.append( qs.get_dict(dict_type=dict_types.QUESTION_ONLY)) question_size = math.ceil(len(questions) / 2) random_positions = random.sample(range(len(questions) - 1), question_size) for position in random_positions: selected_questions.append(questions[position]) exercise_name = " ".join([session["name"], "Post Test"]) exercise_code = " ".join([session["name"], "Post Test"]) exercise = dict(name=exercise_name, transaction_code=exercise_code, company=get_current_company(request), is_post_test=True) serializer = ExerciseSerializer(data=exercise) if serializer.is_valid(): exercise_instance = serializer.save() for exercise_question in selected_questions: exercise_question["exercise"] = exercise_instance.pk exercise_question["question"] = exercise_question["uuid"] serializer = ExerciseQuestionSerializer(data=exercise_question) if serializer.is_valid(): serializer.save() else: raise_error(serializer.errors) session_exercise = dict(session=session["uuid"], exercise=exercise_instance.pk) session_serializer = SessionExerciseSerializer( data=session_exercise) if session_serializer.is_valid(): session_serializer.save() else: raise_error(session_serializer.errors) else: raise_error(serializer.errors) return success_response() except Exception as e: if exercise_instance: exercise_instance.delete() return error_response(str(e))