feature/fix_generate_pass
Evgeniy Shabanov 8 years ago
parent 8d695f1d18
commit 3826ac2037
  1. 2
      access/admin.py
  2. 28
      access/migrations/0004_auto_20180129_0933.py
  3. 88
      access/models/progress.py
  4. 46
      access/serializers.py
  5. 4
      access/urls.py
  6. 107
      access/views.py
  7. 2
      api_v1/urls.py
  8. 4
      csv/load_comments.py
  9. 4
      csv/load_perm.py
  10. 4
      progress/admin.py
  11. 1
      progress/apps.py
  12. 46
      progress/migrations/0001_initial.py
  13. 85
      progress/models.py
  14. 36
      progress/serializers.py
  15. 6
      progress/urls.py
  16. 99
      progress/views.py

@ -1,11 +1,9 @@
from django.contrib import admin from django.contrib import admin
from access.models.other import Invite, Account, ResetPassword, UserActivity from access.models.other import Invite, Account, ResetPassword, UserActivity
from access.models.progress import ProgressLesson
from access.models.user import User from access.models.user import User
admin.site.register(User) admin.site.register(User)
admin.site.register(Account) admin.site.register(Account)
admin.site.register(Invite) admin.site.register(Invite)
admin.site.register(ResetPassword) admin.site.register(ResetPassword)
admin.site.register(ProgressLesson)
admin.site.register(UserActivity) admin.site.register(UserActivity)

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2018-01-25 16:43 # Generated by Django 1.11.6 on 2018-01-29 09:33
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations from django.db import migrations
@ -8,18 +8,10 @@ from django.db import migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = [
('access', '0008_auto_20171220_1325'), ('access', '0003_useractivity'),
] ]
operations = [ operations = [
migrations.RemoveField(
model_name='pivotprogressvertex',
name='progress',
),
migrations.RemoveField(
model_name='pivotprogressvertex',
name='teacher',
),
migrations.AlterUniqueTogether( migrations.AlterUniqueTogether(
name='progress', name='progress',
unique_together=set([]), unique_together=set([]),
@ -32,10 +24,22 @@ class Migration(migrations.Migration):
model_name='progress', model_name='progress',
name='user', name='user',
), ),
migrations.DeleteModel( migrations.AlterUniqueTogether(
name='PivotProgressVertex', name='progresslesson',
unique_together=set([]),
),
migrations.RemoveField(
model_name='progresslesson',
name='progress',
),
migrations.RemoveField(
model_name='progresslesson',
name='teacher',
), ),
migrations.DeleteModel( migrations.DeleteModel(
name='Progress', name='Progress',
), ),
migrations.DeleteModel(
name='ProgressLesson',
),
] ]

@ -1,88 +0,0 @@
from django.conf import settings
from django.contrib.postgres.fields import ArrayField
from django.db import models
from model_utils import Choices
from courses.api import CourseProgressApi
class Progress(models.Model):
hidden_lessons = ArrayField(
models.UUIDField(verbose_name="Токен урока", unique=True, editable=False),
default=[],
verbose_name='Список скрытых уроков',
)
teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь по умолчанию",
related_name='teacher_progress')
user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='Студент')
course_token = models.UUIDField(verbose_name="Токен курса", editable=False)
def progress_status(self, sorted_token_list):
"""
Возвращает порядок активной темы и урока или ничего
:return: (topic_sort, lesson_sort) or None
"""
token_list = [i.lesson_token for i in self.progresslesson_set.filter(status='done')]
x = (1, 1)
for idx_topic, lesson_list in enumerate(sorted_token_list):
for idx_lesson, lesson_token in enumerate(lesson_list):
if lesson_token in token_list:
x = None
elif x is None:
x = (idx_topic+1, idx_lesson+1)
return x
def __str__(self):
return '%s' % (self.user.email,)
class Meta:
verbose_name = 'Прогресс пользователя'
verbose_name_plural = 'Прогресс пользователя'
unique_together = (("user", "course_token"),)
class ProgressLesson(models.Model):
progress = models.ForeignKey(to=Progress)
lesson_token = models.UUIDField(verbose_name="Токен урока", editable=False)
teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь",)
date = models.DateTimeField(verbose_name='Дата зачтения задания', blank=True, null=True)
STATUSES = Choices('done', 'wait', 'fail')
status = models.CharField(choices=STATUSES, default=STATUSES.wait, max_length=20)
comment_tokens = ArrayField(models.UUIDField(verbose_name="Токен комента", editable=False), default=[])
def __str__(self):
return self.progress.user.email
class Meta:
verbose_name = 'Прохождение уроков'
verbose_name_plural = 'Прохождение урока'
unique_together = ('progress', 'lesson_token')
# class UserLessonAnswer(models.Model):
# progress_lesson = models.ForeignKey(to=ProgressLesson)
# date = models.DateTimeField(verbose_name='Дата сдачи', auto_now_add=True)
# reviewer = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Проверяющий",)
#
# class Meta:
# verbose_name = 'Блок ответов пользователя'
# verbose_name_plural = 'Блоки ответов пользователя'
#
#
# class AnswerItem(models.Model):
# STATUSES = Choices('done', 'wait', 'fail')
#
# lesson_answer = models.ForeignKey(to=UserLessonAnswer)
# question = models.TextField(verbose_name='Вопрос') # TODO подумать над хранением токена вопроса
# value = models.TextField(verbose_name='Ответ')
# comment = models.TextField(verbose_name='Комент', blank=True, null=True)
# status = models.CharField(choices=STATUSES, default=STATUSES.wait, max_length=20)
#
# class Meta:
# verbose_name = 'Ответ пользователя'
# verbose_name_plural = 'Ответы пользователя'

@ -2,52 +2,8 @@ from django.contrib.auth import get_user_model
from rest_framework import serializers from rest_framework import serializers
from access.models.other import Account from access.models.other import Account
from access.models.progress import ProgressLesson
from progress.models import Progress
from achievements.serialers import DiplomaSerializer, AchievementsSerializer from achievements.serialers import DiplomaSerializer, AchievementsSerializer
from courses.api import CourseProgressApi from progress.serializers import ProgressSerializer
class ProgressLessonSerializer(serializers.ModelSerializer):
teacher = serializers.SerializerMethodField()
class Meta:
model = ProgressLesson
exclude = ('id', 'progress')
@staticmethod
def get_teacher(self):
return self.teacher.get_full_name()
class ProgressAnalyticSerializer(serializers.ModelSerializer):
name = serializers.SerializerMethodField()
email = serializers.SerializerMethodField()
class Meta:
model = Progress
fields = ('name', 'email',)
@staticmethod
def get_name(self):
return self.user.get_full_name()
@staticmethod
def get_email(self):
return self.user.email
class ProgressSerializer(serializers.ModelSerializer):
lessons = serializers.SerializerMethodField()
class Meta:
model = Progress
fields = ('lessons', 'course_token')
@staticmethod
def get_lessons(self):
return [ProgressLessonSerializer(i).data for i in self.progresslesson_set.all()]
class AccountSerializer(serializers.ModelSerializer): class AccountSerializer(serializers.ModelSerializer):

@ -13,8 +13,4 @@ urlpatterns = [
url(r'login/$', views.LoginView.as_view()), url(r'login/$', views.LoginView.as_view()),
url(r'logout/$', views.LogoutView.as_view()), url(r'logout/$', views.LogoutView.as_view()),
url(r'reset/$', views.ResetPasswordView.as_view()), url(r'reset/$', views.ResetPasswordView.as_view()),
url(r'progress/$', views.UpdateProgress.as_view()),
url(r'progress_detail/upload/(?P<token>[0-9A-Fa-f-]+)/$', views.UploadCourseProgressUserView.as_view()),
url(r'progress_detail/(?P<token>[0-9A-Fa-f-]+)/$', views.CourseProgressUserView.as_view()),
url(r'progress_dynamic/(?P<token>[0-9A-Fa-f-]+)/$', views.CourseProgressDynamicView.as_view()),
] ]

@ -16,10 +16,7 @@ from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from access.models.other import Invite, ResetPassword from access.models.other import Invite, ResetPassword
from access.models.progress import ProgressLesson from access.serializers import UserSelfSerializer, UserSearchSerializer
from progress.models import Progress
from access.serializers import UserSelfSerializer, UserSearchSerializer, ProgressLessonSerializer, \
ProgressAnalyticSerializer
from courses.api import CourseProgressApi from courses.api import CourseProgressApi
@ -236,41 +233,6 @@ class LogoutView(APIView):
return Response(status=204) return Response(status=204)
class UpdateProgress(APIView):
renderer_classes = (JSONRenderer,)
@staticmethod
def post(request):
"""
На вход обязательно передаётся параметр id (id узла).
"""
lesson_token = request.JSON.get('lesson_token', None)
course_token = request.JSON.get('course_token', None)
if lesson_token is None or course_token is None:
return Response('Не передан слаг курса или токен урока', status=400)
try:
p = Progress.objects.get(user=request.user, course_token=course_token)
try:
pv = ProgressLesson.objects.get(
progress=p,
lesson_token=lesson_token,
)
except ProgressLesson.DoesNotExist:
pv = ProgressLesson.objects.create(
date=datetime.datetime.now(),
teacher=p.teacher,
progress=p,
lesson_token=lesson_token,
)
pv.status = ProgressLesson.STATUSES.done
pv.save()
return Response(ProgressLessonSerializer(pv).data, status=200)
except Progress.DoesNotExist:
return Response('Не найден прогресс по заданным параметрам', status=404)
class UserGuardView(APIView): class UserGuardView(APIView):
renderer_classes = (JSONRenderer,) renderer_classes = (JSONRenderer,)
permission_classes = (IsAuthenticated,) permission_classes = (IsAuthenticated,)
@ -303,73 +265,6 @@ class UserGuardView(APIView):
return res_403 return res_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()
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 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 MinUserView(APIView): class MinUserView(APIView):
renderer_classes = (JSONRenderer,) renderer_classes = (JSONRenderer,)

@ -4,7 +4,7 @@ urlpatterns = [
url(r'courses/', include('courses.urls')), url(r'courses/', include('courses.urls')),
url(r'users/', include('access.urls')), url(r'users/', include('access.urls')),
url(r'library/', include('library.urls')), url(r'library/', include('library.urls')),
# url(r'finance/', include('finance.urls')), url(r'finance/', include('finance.urls')),
url(r'storage/', include('storage.urls')), url(r'storage/', include('storage.urls')),
url(r'progress/', include('progress.urls')), url(r'progress/', include('progress.urls')),
] ]

@ -1,6 +1,4 @@
import csv import csv
import random
import string
import django import django
import os import os
@ -15,7 +13,7 @@ django.setup()
from storage.models import Comment, File from storage.models import Comment, File
from courses.models import Lesson from courses.models import Lesson
from access.models.progress import ProgressLesson, Progress from progress.models import ProgressLesson, Progress
if __name__ == '__main__': if __name__ == '__main__':
csv.field_size_limit(500 * 1024 * 1024) csv.field_size_limit(500 * 1024 * 1024)

@ -14,10 +14,10 @@ django.setup()
from django.contrib.auth.models import Group from django.contrib.auth.models import Group
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from access.models.progress import ProgressLesson from progress.models import ProgressLesson, Progress
from progress.models import Progress
from courses.models import Lesson, Course from courses.models import Lesson, Course
if __name__ == '__main__': if __name__ == '__main__':
Progress.objects.all().delete() Progress.objects.all().delete()
ProgressLesson.objects.all().delete() ProgressLesson.objects.all().delete()

@ -1,6 +1,8 @@
from django.contrib import admin from django.contrib import admin
# Register your models here. # Register your models here.
from progress.models import Progress from progress.models import ProgressLesson, Progress
admin.site.register(Progress) admin.site.register(Progress)
admin.site.register(ProgressLesson)

@ -1,4 +1,3 @@
# -*- coding: utf-8 -*-
from django.apps import AppConfig from django.apps import AppConfig

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2018-01-25 16:41 # Generated by Django 1.11.6 on 2018-01-29 09:31
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
@ -17,42 +17,42 @@ class Migration(migrations.Migration):
] ]
operations = [ operations = [
migrations.CreateModel(
name='PivotProgressVertex',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('vertex', models.CharField(blank=True, max_length=15, verbose_name='Ссылки на узлы')),
('status', models.SmallIntegerField(choices=[(2, 'Выполненно'), (1, 'Ожидание'), (0, 'Не выполненно')], default=0)),
('comment', django.contrib.postgres.fields.ArrayField(base_field=models.CharField(max_length=15, unique=True, verbose_name='Ссылки на комменты'), default=[], size=None)),
('date', models.DateTimeField(blank=True, null=True, verbose_name='Дата зачтения задания')),
],
),
migrations.CreateModel( migrations.CreateModel(
name='Progress', name='Progress',
fields=[ fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('route', models.CharField(blank=True, max_length=15, null=True, verbose_name='Токен прохождения')), ('hidden_lessons', django.contrib.postgres.fields.ArrayField(base_field=models.UUIDField(editable=False, unique=True, verbose_name='Токен урока'), default=[], size=None, verbose_name='Список скрытых уроков')),
('course', models.CharField(max_length=127, verbose_name='Слаг курса')), ('course_token', models.UUIDField(editable=False, verbose_name='Токен курса')),
('teacher', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teacher_progress', to=settings.AUTH_USER_MODEL, verbose_name='Преподователь по умолчанию')), ('teacher', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='teacher_progress', to=settings.AUTH_USER_MODEL, verbose_name='Преподователь по умолчанию')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент')), ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент')),
], ],
options={ options={
'verbose_name_plural': 'Прогресс пользователя',
'verbose_name': 'Прогресс пользователя', 'verbose_name': 'Прогресс пользователя',
'verbose_name_plural': 'Прогресс пользователя',
}, },
), ),
migrations.AddField( migrations.CreateModel(
model_name='pivotprogressvertex', name='ProgressLesson',
name='progress', fields=[
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='progress.Progress'), ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('lesson_token', models.UUIDField(editable=False, verbose_name='Токен урока')),
('date', models.DateTimeField(blank=True, null=True, verbose_name='Дата зачтения задания')),
('status', models.CharField(choices=[('done', 'done'), ('wait', 'wait'), ('fail', 'fail')], default='wait', max_length=20)),
('comment_tokens', django.contrib.postgres.fields.ArrayField(base_field=models.UUIDField(editable=False, verbose_name='Токен комента'), default=[], size=None)),
('progress', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='progress.Progress')),
('teacher', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Преподователь')),
],
options={
'verbose_name': 'Прохождение уроков',
'verbose_name_plural': 'Прохождение урока',
},
), ),
migrations.AddField( migrations.AlterUniqueTogether(
model_name='pivotprogressvertex', name='progresslesson',
name='teacher', unique_together=set([('progress', 'lesson_token')]),
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Преподователь'),
), ),
migrations.AlterUniqueTogether( migrations.AlterUniqueTogether(
name='progress', name='progress',
unique_together=set([('user', 'route')]), unique_together=set([('user', 'course_token')]),
), ),
] ]

@ -1,16 +1,41 @@
from django.conf import settings from django.conf import settings
from django.contrib.postgres.fields import ArrayField from django.contrib.postgres.fields import ArrayField
from django.db import models from django.db import models
from model_utils import Choices
# Create your models here. from courses.api import CourseProgressApi
class Progress(models.Model): class Progress(models.Model):
hidden_lessons = ArrayField(
models.UUIDField(verbose_name="Токен урока", unique=True, editable=False),
default=[],
verbose_name='Список скрытых уроков',
)
teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь по умолчанию", teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь по умолчанию",
related_name='teacher_progress') related_name='teacher_progress')
user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='Студент') user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='Студент')
route = models.CharField(max_length=15, verbose_name='Токен прохождения', blank=True, null=True) course_token = models.UUIDField(verbose_name="Токен курса", editable=False)
course = models.CharField(max_length=127, verbose_name='Слаг курса')
def progress_status(self, sorted_token_list):
"""
Возвращает порядок активной темы и урока или ничего
:return: (topic_sort, lesson_sort) or None
"""
token_list = [i.lesson_token for i in self.progresslesson_set.filter(status='done')]
x = (1, 1)
for idx_topic, lesson_list in enumerate(sorted_token_list):
for idx_lesson, lesson_token in enumerate(lesson_list):
if lesson_token in token_list:
x = None
elif x is None:
x = (idx_topic+1, idx_lesson+1)
return x
def __str__(self): def __str__(self):
return '%s' % (self.user.email,) return '%s' % (self.user.email,)
@ -18,18 +43,46 @@ class Progress(models.Model):
class Meta: class Meta:
verbose_name = 'Прогресс пользователя' verbose_name = 'Прогресс пользователя'
verbose_name_plural = 'Прогресс пользователя' verbose_name_plural = 'Прогресс пользователя'
unique_together = (("user", "route"),) unique_together = (("user", "course_token"),)
class PivotProgressVertex(models.Model): class ProgressLesson(models.Model):
VERTEX_STATUS = (
(2, 'Выполненно'),
(1, 'Ожидание'),
(0, 'Не выполненно'),
)
teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь",)
progress = models.ForeignKey(to=Progress) progress = models.ForeignKey(to=Progress)
vertex = models.CharField(max_length=15, blank=True, verbose_name='Ссылки на узлы') lesson_token = models.UUIDField(verbose_name="Токен урока", editable=False)
status = models.SmallIntegerField(choices=VERTEX_STATUS, default=0) teacher = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Преподователь",)
comment = ArrayField(models.CharField(max_length=15, verbose_name='Ссылки на комменты', unique=True), default=[]) date = models.DateTimeField(verbose_name='Дата зачтения задания', blank=True, null=True)
date = models.DateTimeField(verbose_name='Дата зачтения задания', blank=True, null=True) STATUSES = Choices('done', 'wait', 'fail')
status = models.CharField(choices=STATUSES, default=STATUSES.wait, max_length=20)
comment_tokens = ArrayField(models.UUIDField(verbose_name="Токен комента", editable=False), default=[])
def __str__(self):
return self.progress.user.email
class Meta:
verbose_name = 'Прохождение уроков'
verbose_name_plural = 'Прохождение урока'
unique_together = ('progress', 'lesson_token')
# class UserLessonAnswer(models.Model):
# progress_lesson = models.ForeignKey(to=ProgressLesson)
# date = models.DateTimeField(verbose_name='Дата сдачи', auto_now_add=True)
# reviewer = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name="Проверяющий",)
#
# class Meta:
# verbose_name = 'Блок ответов пользователя'
# verbose_name_plural = 'Блоки ответов пользователя'
#
#
# class AnswerItem(models.Model):
# STATUSES = Choices('done', 'wait', 'fail')
#
# lesson_answer = models.ForeignKey(to=UserLessonAnswer)
# question = models.TextField(verbose_name='Вопрос') # TODO подумать над хранением токена вопроса
# value = models.TextField(verbose_name='Ответ')
# comment = models.TextField(verbose_name='Комент', blank=True, null=True)
# status = models.CharField(choices=STATUSES, default=STATUSES.wait, max_length=20)
#
# class Meta:
# verbose_name = 'Ответ пользователя'
# verbose_name_plural = 'Ответы пользователя'

@ -1,32 +1,44 @@
from rest_framework import serializers from rest_framework import serializers
from .models import PivotProgressVertex, Progress from progress.models import ProgressLesson, Progress
class PivotProgressSerializer(serializers.ModelSerializer): class ProgressLessonSerializer(serializers.ModelSerializer):
status = serializers.SerializerMethodField()
teacher = serializers.SerializerMethodField() teacher = serializers.SerializerMethodField()
class Meta: class Meta:
model = PivotProgressVertex model = ProgressLesson
exclude = ('id', 'progress') exclude = ('id', 'progress')
@staticmethod
def get_status(self):
return self.get_status_display()
@staticmethod @staticmethod
def get_teacher(self): def get_teacher(self):
return self.teacher.get_full_name() return self.teacher.get_full_name()
class ProgressAnalyticSerializer(serializers.ModelSerializer):
name = serializers.SerializerMethodField()
email = serializers.SerializerMethodField()
class Meta:
model = Progress
fields = ('name', 'email',)
@staticmethod
def get_name(self):
return self.user.get_full_name()
@staticmethod
def get_email(self):
return self.user.email
class ProgressSerializer(serializers.ModelSerializer): class ProgressSerializer(serializers.ModelSerializer):
vertexes = serializers.SerializerMethodField() lessons = serializers.SerializerMethodField()
class Meta: class Meta:
model = Progress model = Progress
fields = ('route', 'vertexes', 'course') fields = ('lessons', 'course_token')
@staticmethod @staticmethod
def get_vertexes(self): def get_lessons(self):
return [PivotProgressSerializer(i).data for i in self.pivotprogressvertex_set.all()] return [ProgressLessonSerializer(i).data for i in self.progresslesson_set.all()]

@ -2,6 +2,10 @@ from django.conf.urls import url
from progress import views from progress import views
urlpatterns = [ urlpatterns = [
url(r'$', views.UpdateProgress.as_view()), url(r'$', views.UpdateProgress.as_view()),
] url(r'progress_detail/upload/(?P<token>[0-9A-Fa-f-]+)/$', views.UploadCourseProgressUserView.as_view()),
url(r'progress_detail/(?P<token>[0-9A-Fa-f-]+)/$', views.CourseProgressUserView.as_view()),
url(r'progress_dynamic/(?P<token>[0-9A-Fa-f-]+)/$', views.CourseProgressDynamicView.as_view()),
]

@ -1,14 +1,18 @@
import datetime import datetime
import csv
from django.http import HttpResponse
from django.shortcuts import render from django.shortcuts import render
# Create your views here. # Create your views here.
from rest_framework.exceptions import ValidationError
from rest_framework.renderers import JSONRenderer from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response from rest_framework.response import Response
from rest_framework.views import APIView from rest_framework.views import APIView
from .models import Progress, PivotProgressVertex from courses.api import CourseProgressApi
from .serializers import PivotProgressSerializer from progress.models import Progress, ProgressLesson
from progress.serializers import ProgressLessonSerializer, ProgressAnalyticSerializer
class UpdateProgress(APIView): class UpdateProgress(APIView):
@ -19,28 +23,95 @@ class UpdateProgress(APIView):
""" """
На вход обязательно передаётся параметр id (id узла). На вход обязательно передаётся параметр id (id узла).
""" """
token = request.JSON.get('token', None) lesson_token = request.JSON.get('lesson_token', None)
course = request.JSON.get('slug', None) course_token = request.JSON.get('course_token', None)
if token is None or course is None: if lesson_token is None or course_token is None:
return Response('Не передан слаг курса или токен урока', status=400) return Response('Не передан слаг курса или токен урока', status=400)
try: try:
p = Progress.objects.get(user=request.user, course=course) p = Progress.objects.get(user=request.user, course_token=course_token)
try: try:
pv = PivotProgressVertex.objects.get( pv = ProgressLesson.objects.get(
progress=p, progress=p,
vertex=token, lesson_token=lesson_token,
) )
except PivotProgressVertex.DoesNotExist: except ProgressLesson.DoesNotExist:
pv = PivotProgressVertex.objects.create( pv = ProgressLesson.objects.create(
date=datetime.datetime.now(), date=datetime.datetime.now(),
teacher=p.teacher, teacher=p.teacher,
progress=p, progress=p,
vertex=token, lesson_token=lesson_token,
) )
pv.status = 2 pv.status = ProgressLesson.STATUSES.done
pv.save() pv.save()
return Response(PivotProgressSerializer(pv).data, status=200) return Response(ProgressLessonSerializer(pv).data, status=200)
except Progress.DoesNotExist: except Progress.DoesNotExist:
return Response('Не найден прогресс по заданным параметрам', status=404) return Response('Не найден прогресс по заданным параметрам', status=404)
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()
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 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)

Loading…
Cancel
Save