import csv import datetime from django.contrib.auth import get_user_model from django.core.exceptions import ValidationError from django.http import HttpResponse from rest_framework.permissions import IsAuthenticated from rest_framework.renderers import JSONRenderer from rest_framework.response import Response from rest_framework.views import APIView from django.db.models import Q from progress.models import ProgressLesson, Progress from progress.serializers import ProgressAnalyticSerializer, ProgressLessonSerializer from courses.api import CourseProgressApi from progress.tasks import add_next_lesson class StudentWorkView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def get(request, teacher_token): client_status = request.GET.get('status', 'in_progress') server_status = Q(status='fail') if \ client_status == 'not_done' else Q(status='wait') if client_status == 'in_progress' else Q(status='done') if request.user.is_authenticated() and request.user.groups.filter(name__in=['teachers', 'admin']).exists(): try: progress_lessons = ProgressLesson.objects.filter( ~Q(progress__user__out_key=teacher_token), server_status, checker__out_key=teacher_token, ) return Response([ProgressLessonSerializer(i).data for i in progress_lessons], status=200) except ValidationError: return Response("Bad request", status=400) return Response(status=403) class CourseProgressDynamicView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def get(request, token): if request.user.is_authenticated() and request.user.is_staff: try: progresses = Progress.objects.filter(course_token=token) res = {} for i in progresses: key = i.progresslesson_set.filter(status="done").count() + 1 res[key] = 1 if not key in res.keys() else res[key] + 1 return Response(res, status=200) except ValidationError: return Response("Bad request", status=400) return Response(status=403) class CourseProgressUserView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def get(request, token): if request.user.is_authenticated() and request.user.is_staff: try: res = [] sorted_token_list = CourseProgressApi.get_topic_lesson(token) for p in Progress.objects.filter(course_token=token): progress = ProgressAnalyticSerializer(p).data progress['progress_course'] = p.progress_status(sorted_token_list) res.append(progress) return Response(res, status=200) except ValidationError: return Response("Bad request", status=400) return Response(status=403) class TeacherUpdateProgress(APIView): renderer_classes = (JSONRenderer,) @staticmethod def post(request): lesson_token = request.JSON.get('lesson_token', None) course_token = request.JSON.get('course_token', None) student_out_key = request.JSON.get('student_out_key', None) action = request.JSON.get('action', None) comment = request.JSON.get('comment', None) if lesson_token is None or course_token is None: return Response('Не передан слаг курса или токен урока', status=400) if student_out_key is None: return Response('Не передан student_out_key', status=400) try: student = get_user_model().objects.get(out_key=student_out_key) p = Progress.objects.get( user=student, teacher=request.user, course_token=course_token, ) try: pv = ProgressLesson.objects.get( progress=p, lesson_token=lesson_token, ) if pv.status == ProgressLesson.STATUSES.wait: if action == "no": pv.status = ProgressLesson.STATUSES.fail elif action == "yes": pv.status = ProgressLesson.STATUSES.done pv.finish_date = datetime.datetime.now() else: Response("Свойство action должно иметь значение либо done, либо fail", status=400) else: return Response("Ошибка прав доступа", status=403) pv.comment_tokens.append(comment) except ProgressLesson.DoesNotExist: return Response('Урок не проходится этим пользователем', status=403) pv.save() res = {"current": ProgressLessonSerializer(pv).data} if pv.status == ProgressLesson.STATUSES.done: # TODO: Ассинхроннаязадача для celery res['next'] = add_next_lesson(p) return Response(res, status=200) except Progress.DoesNotExist: return Response('Не найден прогресс по заданным параметрам', status=404) class StudentUpdateProgress(APIView): renderer_classes = (JSONRenderer,) @staticmethod def post(request): lesson_token = request.JSON.get('lesson_token', None) course_token = request.JSON.get('course_token', None) comment = request.JSON.get('comment', None) if lesson_token is None or course_token is None: return Response('Не передан слаг курса или токен урока', status=400) try: student = request.user p = Progress.objects.get(user=student, course_token=course_token) try: pv = ProgressLesson.objects.get( progress=p, lesson_token=lesson_token, ) if not pv.status == ProgressLesson.STATUSES.wait \ and not pv.status == ProgressLesson.STATUSES.done: if pv.checker == p.teacher: pv.status = ProgressLesson.STATUSES.wait pv.comment_tokens.append(comment) elif pv.checker == p.user: pv.status = ProgressLesson.STATUSES.done pv.finish_date = datetime.datetime.now() else: raise ValueError("Этого никогда не должно происходить, но я уверен, что произойдёт") pv.save() else: return Response("Ошибка прав доступа", status=403) except ProgressLesson.DoesNotExist: return Response('Урок не проходится этим пользователем', status=403) res = {"current": ProgressLessonSerializer(pv).data} if pv.status == ProgressLesson.STATUSES.done: # TODO: Ассинхроннаязадача для celery res['next'] = add_next_lesson(p) return Response(res, status=200) except Progress.DoesNotExist: return Response('Не найден прогресс по заданным параметрам', status=404) class UploadCourseProgressUserView(APIView): renderer_classes = (JSONRenderer,) @staticmethod def get(request, token): if request.user.is_authenticated() and request.user.is_staff: try: response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="%s.csv"' % token sorted_token_list = CourseProgressApi.get_topic_lesson(token) writer = csv.writer(response) writer.writerow(['Имя', 'Почта', 'Последняя тема', 'Последний урок']) for p in Progress.objects.filter(course_token=token): progress = ProgressAnalyticSerializer(p).data progress['progress_course'] = p.progress_status(sorted_token_list) writer.writerow([ progress['name'], progress['email'], progress['progress_course'] and progress['progress_course'][0], progress['progress_course'] and progress['progress_course'][1], ]) return response except ValidationError: return Response("Bad request", status=400) return Response(status=403) class UserGuardView(APIView): renderer_classes = (JSONRenderer,) permission_classes = (IsAuthenticated,) @staticmethod def get(request, pk, page): try: user = get_user_model().objects.get(out_key=pk) except get_user_model().DoesNotExist: return Response("User doesn't exist", status=404) is_i = request.user == user res_403 = Response('Permission denied', status=403) res_204 = Response(status=204) if is_i and not request.user.groups.filter(name='teachers').exists() and page == 'homeworks': return res_403 if is_i and not \ request.user.groups.filter(name__in=['students', 'managers', 'lead_managers']).exists() \ and page == 'payment': return res_403 if is_i: return res_204 if page == 'profile' and (request.user.is_superuser or request.user.is_staff): return res_204 return res_403