feature/fix_generate_pass
Andrey 8 years ago
parent 84143ebeb4
commit afb70f10d9
  1. 3
      access/admin.py
  2. 4
      access/migrations/0001_initial.py
  3. 6
      access/models/__init__.py
  4. 68
      access/models/other.py
  5. 84
      access/models/user.py
  6. 43
      access/serializers.py
  7. 13
      access/views.py
  8. 19
      courses/serializers.py
  9. 31
      courses/views.py
  10. 15
      csv/load_courses.py
  11. 2
      csv/load_perm.py
  12. 2
      csv/load_student_teachers_threads.py
  13. 2
      csv/load_users.py
  14. 2
      finance/signals.py
  15. 3
      journals/default_threads.py
  16. 2
      journals/views.py
  17. 20
      maps/migrations/0005_coursemap_name.py
  18. 49
      maps/models.py
  19. 22
      maps/serializers.py

@ -1,5 +1,6 @@
from django.contrib import admin from django.contrib import admin
from access.models import Progress, User, Account, Invite from access.models.other import Invite, Account, Progress
from access.models.user import User
admin.site.register(User) admin.site.register(User)
admin.site.register(Account) admin.site.register(Account)

@ -5,6 +5,8 @@ from __future__ import unicode_literals
import access.models import access.models
from django.db import migrations, models from django.db import migrations, models
import access.models.user
class Migration(migrations.Migration): class Migration(migrations.Migration):
@ -34,7 +36,7 @@ class Migration(migrations.Migration):
'verbose_name_plural': 'Пользователи', 'verbose_name_plural': 'Пользователи',
}, },
managers=[ managers=[
('objects', access.models.CustomUserManager()), ('objects', access.models.user.CustomUserManager()),
], ],
), ),
migrations.CreateModel( migrations.CreateModel(

@ -0,0 +1,6 @@
# encoding=utf-8
from .other import Account, Progress, Invite
from .user import User

@ -0,0 +1,68 @@
from django.conf import settings
from django.db import models
from courses.models import Course, Vertex
from maps.models import CourseRoute
class Invite(models.Model):
owner = models.OneToOneField(to=settings.AUTH_USER_MODEL, null=True)
hash = models.CharField(max_length=15)
date = models.DateTimeField(null=True, blank=True)
class Meta:
verbose_name = 'Приглошение в систему'
verbose_name_plural = 'Приглошения в систему'
class Account(models.Model):
GENDER_CHOICES = (
(0, 'undefined'),
(1, 'male'),
(2, 'female'),
)
b_day = models.DateField(blank=True, null=True)
city = models.CharField(max_length=63, null=True, blank=True)
gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0)
owner = models.OneToOneField(to=settings.AUTH_USER_MODEL, null=True)
photo = models.ImageField(null=True, blank=True, default='/static/default/access/default.png', upload_to='user/photo/')
phone = models.CharField(max_length=15, null=True, blank=True)
def __str__(self):
return self.owner.email
class Meta:
verbose_name = 'Дополнительная информация о пользователе'
verbose_name_plural = 'Дополнительная информация о пользователе'
class Progress(models.Model):
user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='Студент', null=True)
course = models.ForeignKey(to=Course, verbose_name='Курс', null=True)
progress_list = models.ManyToManyField(to=Vertex, verbose_name='Лист пройденных объектов', blank=True)
template = models.OneToOneField(to=CourseRoute, blank=True, null=True, verbose_name='Шаблон для прохождения если '
'не указан явно смотри '
'функцию get_template()')
def __str__(self):
return '%s %s' % (
self.user.email,
self.course.title,
)
def get_template(self):
return self.template if self.template else self.course.route
def is_finish(self):
return self.get_template().is_finish(self.user)
def get_objects_in_progress(self):
return self.get_template().get_active_objects(self.user)
def is_access(self, vertex):
return vertex in self.progress_list.all() or vertex == self.get_objects_in_progress()
class Meta:
verbose_name = 'Прогресс пользователя'
verbose_name_plural = 'Прогресс пользователя'
unique_together = (("user", "course"),)

@ -1,56 +1,16 @@
# encoding=utf-8
import random import random
import string import string
from django.contrib.contenttypes.models import ContentType from django.contrib.auth.base_user import BaseUserManager, AbstractBaseUser
from django_celery_results.models import TaskResult from django.contrib.auth.models import Group, PermissionsMixin
from courses.models import Vertex, Course
from maps.models import CourseMap, CourseRoute
from storage.models import Storage
from django.core.mail import send_mail from django.core.mail import send_mail
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from django.contrib.auth.models import PermissionsMixin, Group
from django.db import models from django.db import models
from django.conf import settings
from django.utils import timezone from django.utils import timezone
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from lms.global_decorators import transaction_decorator
from journals.models import Journal, Thread, ACTION_CHOICES
class Invite(models.Model): from access.models.other import Invite, Account
owner = models.OneToOneField(to=settings.AUTH_USER_MODEL, null=True) from journals.models import Thread
hash = models.CharField(max_length=15) from lms.global_decorators import transaction_decorator
date = models.DateTimeField(null=True, blank=True)
class Meta:
verbose_name = 'Приглошение в систему'
verbose_name_plural = 'Приглошения в систему'
class Account(models.Model):
GENDER_CHOICES = (
(0, 'undefined'),
(1, 'male'),
(2, 'female'),
)
b_day = models.DateField(blank=True, null=True)
city = models.CharField(max_length=63, null=True, blank=True)
gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0)
owner = models.OneToOneField(to=settings.AUTH_USER_MODEL, null=True)
photo = models.ImageField(null=True, blank=True, default='/static/default/access/default.png', upload_to='user/photo/')
phone = models.CharField(max_length=15, null=True, blank=True)
def __str__(self):
return self.owner.email
class Meta:
verbose_name = 'Дополнительная информация о пользователе'
verbose_name_plural = 'Дополнительная информация о пользователе'
class CustomUserManager(BaseUserManager): class CustomUserManager(BaseUserManager):
@ -170,36 +130,4 @@ class User(AbstractBaseUser, PermissionsMixin):
class Meta: class Meta:
verbose_name = _('Пользователь') verbose_name = _('Пользователь')
verbose_name_plural = _('Пользователи') verbose_name_plural = _('Пользователи')
class Progress(models.Model):
user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='Студент', null=True)
course = models.ForeignKey(to=Course, verbose_name='Курс', null=True)
progress_list = models.ManyToManyField(to=Vertex, verbose_name='Лист пройденных объектов', blank=True)
template = models.OneToOneField(to=CourseRoute, blank=True, null=True, verbose_name='Шаблон для прохождения если '
'не указан явно смотри '
'функцию get_template()')
def __str__(self):
return '%s %s' % (
self.user.email,
self.course.title,
)
def get_template(self):
return self.template if self.template else self.course.route
def is_finish(self):
return self.get_template().is_finish(self.user)
def get_objects_in_progress(self):
return self.get_template().get_active_objects(self.user)
def is_access(self, vertex):
return vertex in self.progress_list
class Meta:
verbose_name = 'Прогресс пользователя'
verbose_name_plural = 'Прогресс пользователя'
unique_together = (("user", "course"),)

@ -1,36 +1,36 @@
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from rest_framework import serializers from rest_framework import serializers
from access.models import Account, Progress from access.models.other import Account, Progress
from maps.serializers import CourseRouteSerializer from courses.serializers import MiniVertexSerializer, CourseInitSerializer
class ProgressSerializer(serializers.ModelSerializer): class ProgressSerializer(serializers.ModelSerializer):
template = serializers.SerializerMethodField()
course = serializers.SerializerMethodField()
max = serializers.SerializerMethodField() max = serializers.SerializerMethodField()
number = serializers.SerializerMethodField() number = serializers.SerializerMethodField()
in_progress = serializers.SerializerMethodField()
course = serializers.SerializerMethodField()
class Meta: class Meta:
model = Progress model = Progress
fields = ('course', 'template', 'number', 'max', 'progress_list', ) fields = ('in_progress', 'number', 'max', 'progress_list', 'course')
@staticmethod @staticmethod
def get_max(self): def get_max(self):
return self.course.get_vertexes('topic').count() return self.course.get_vertexes('topic').count()
@staticmethod @staticmethod
def get_number(self): def get_course(self):
if self.is_finish(): return CourseInitSerializer(self.course).data
return self.get_max()
return self.progress_list.filter(content_type__model="topic").count()
@staticmethod @staticmethod
def get_course(self): def get_in_progress(self):
return {'title': self.course.title, 'slug': self.course.slug} return [MiniVertexSerializer(i).data for i in self.get_objects_in_progress()]
@staticmethod @staticmethod
def get_template(self): def get_number(self):
return CourseRouteSerializer(self.get_template()).data if self.is_finish():
return self.get_max()
return self.progress_list.filter(content_type__model="topic").count()
class AccountSerializer(serializers.ModelSerializer): class AccountSerializer(serializers.ModelSerializer):
@ -45,13 +45,15 @@ class AccountSerializer(serializers.ModelSerializer):
return self.get_gender_display() return self.get_gender_display()
class UserInitSerializer(serializers.ModelSerializer): class UserSelfSerializer(serializers.ModelSerializer):
account = serializers.SerializerMethodField() account = serializers.SerializerMethodField()
groups = serializers.SerializerMethodField() groups = serializers.SerializerMethodField()
progress = serializers.SerializerMethodField()
class Meta: class Meta:
model = get_user_model() model = get_user_model()
fields = ('id', 'email', 'first_name', 'last_name', 'account', 'groups', 'is_staff', 'is_superuser') fields = ('id', 'email', 'first_name', 'last_name','progress',
'account', 'groups', 'is_staff', 'is_superuser')
@staticmethod @staticmethod
def get_account(self): def get_account(self):
@ -61,23 +63,22 @@ class UserInitSerializer(serializers.ModelSerializer):
def get_groups(self): def get_groups(self):
return [group.name for group in self.groups.all()] return [group.name for group in self.groups.all()]
@staticmethod
def get_progress(self):
return [ProgressSerializer(i).data for i in self.progress_set.all()]
class UserProfileSerializer(serializers.ModelSerializer): class UserProfileSerializer(serializers.ModelSerializer):
account = serializers.SerializerMethodField() account = serializers.SerializerMethodField()
groups = serializers.SerializerMethodField() groups = serializers.SerializerMethodField()
progress = serializers.SerializerMethodField()
class Meta: class Meta:
model = get_user_model() model = get_user_model()
fields = ( fields = (
'id', 'email', 'first_name', 'last_name','progress', 'id', 'email', 'first_name', 'last_name',
'account', 'groups', 'is_staff', 'is_superuser', 'account', 'groups', 'is_staff', 'is_superuser',
) )
@staticmethod
def get_progress(self):
return [ProgressSerializer(i).data for i in self.progress_set.all()]
@staticmethod @staticmethod
def get_account(self): def get_account(self):
return AccountSerializer(self.account).data return AccountSerializer(self.account).data

@ -7,8 +7,8 @@ from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response from rest_framework.response import Response
from django.db.models import Q from django.db.models import Q
from access.models import Invite, Progress from access.models.other import Invite, Progress
from access.serializers import UserInitSerializer, UserSearchSerializer, UserProfileSerializer from access.serializers import UserSelfSerializer, UserSearchSerializer, UserProfileSerializer
from courses.models import Vertex from courses.models import Vertex
from journals.models import Thread from journals.models import Thread
@ -37,7 +37,7 @@ class InfoUserView(APIView):
def get(self, request): def get(self, request):
if request.user.is_authenticated(): if request.user.is_authenticated():
return Response(UserInitSerializer(request.user).data, status=self.status_code) return Response(UserSelfSerializer(request.user).data, status=self.status_code)
return Response('anonymous', status=self.status_code) return Response('anonymous', status=self.status_code)
@ -85,8 +85,7 @@ class DetailUserView(APIView):
except get_user_model().DoesNotExist: except get_user_model().DoesNotExist:
return Response("User doesn't exist", status=404) return Response("User doesn't exist", status=404)
serialized_user = UserProfileSerializer(user).data serialized_user = UserSelfSerializer(user).data
serialized_user['is_i'] = request.user == user serialized_user['is_i'] = request.user == user
return Response(serialized_user, status=200) return Response(serialized_user, status=200)
@ -126,7 +125,7 @@ class RegistrationView(APIView):
email=request.JSON['email'].lower(), email=request.JSON['email'].lower(),
) )
return Response(UserInitSerializer(user).data, status=200) return Response(UserSelfSerializer(user).data, status=200)
class ChangePasswordView(APIView): class ChangePasswordView(APIView):
@ -152,7 +151,7 @@ class LoginView(APIView):
auth.login(request, user) auth.login(request, user)
except AttributeError: except AttributeError:
return Response("Неверный пароль", status=404) return Response("Неверный пароль", status=404)
return Response(UserInitSerializer(request.user).data, status=200) return Response(UserSelfSerializer(request.user).data, status=200)
class LogoutView(APIView): class LogoutView(APIView):

@ -61,6 +61,13 @@ class VertexSerializer(MiniVertexSerializer):
return False return False
class CourseInitSerializer(serializers.ModelSerializer):
class Meta:
model = Course
fields = ['title', 'slug']
class CourseListSerializer(serializers.ModelSerializer): class CourseListSerializer(serializers.ModelSerializer):
statistic = serializers.SerializerMethodField() statistic = serializers.SerializerMethodField()
level = serializers.SerializerMethodField() level = serializers.SerializerMethodField()
@ -84,18 +91,6 @@ class CourseListSerializer(serializers.ModelSerializer):
return self.get_direction_display() return self.get_direction_display()
class CourseTreeSerializer(serializers.ModelSerializer):
route = serializers.SerializerMethodField()
class Meta:
model = Course
fields = ['id', 'route']
@staticmethod
def get_route(self):
return CourseRouteSerializer(self.route).data
class CourseDetailSerializer(serializers.ModelSerializer): class CourseDetailSerializer(serializers.ModelSerializer):
level = serializers.SerializerMethodField() level = serializers.SerializerMethodField()
direction = serializers.SerializerMethodField() direction = serializers.SerializerMethodField()

@ -2,10 +2,9 @@ from rest_framework.views import APIView
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 access.serializers import ProgressSerializer from maps.serializers import CourseMapSerializer
from courses.models import Course, Vertex from courses.models import Course, Vertex
from access.models import Progress from courses.serializers import CourseDetailSerializer, CourseListSerializer, VertexSerializer
from courses.serializers import CourseDetailSerializer, CourseListSerializer, VertexSerializer, CourseTreeSerializer
from journals.models import Thread from journals.models import Thread
@ -25,21 +24,11 @@ class TreeView(APIView):
except Course.DoesNotExist: except Course.DoesNotExist:
return Response("Course doesn't exist", status=404) return Response("Course doesn't exist", status=404)
res = CourseTreeSerializer(course).data if request.user.is_authenticated():
route = course.progress_set.get(user=request.user).get_template()
return Response(CourseMapSerializer(route.get_first()).data, self.status_code)
if not request.user.is_authenticated(): return Response(CourseMapSerializer(course.route.get_first()).data, self.status_code)
res['active_id'] = False
res['extra_privilege'] = []
return Response(res, self.status_code)
try:
res['progress'] = ProgressSerializer(
Progress.objects.get(course=course, user=request.user)
).data
except Progress.DoesNotExist:
res['progress'] = False
return Response(res, self.status_code)
class CourseDetailView(APIView): class CourseDetailView(APIView):
@ -69,14 +58,8 @@ class CourseListView(APIView):
course_list = Course.objects.all() course_list = Course.objects.all()
else: else:
course_list = Course.objects.filter(public=True) course_list = Course.objects.filter(public=True)
res = []
for course in course_list:
course_serialize = CourseListSerializer(course).data
course_serialize['is_mine'] = False
if request.user.is_authenticated() and Progress.objects.filter(course=course, user=request.user).exists():
course_serialize['is_mine'] = True
res.append(course_serialize)
res = [CourseListSerializer(course).data for course in course_list]
return Response(res, self.status_code) return Response(res, self.status_code)

@ -36,11 +36,11 @@ if __name__ == '__main__':
except IntegrityError: except IntegrityError:
pass pass
# with open('./course/storage.csv') as storage_csv: with open('./course/storage.csv') as storage_csv:
# storage_reader = csv.DictReader(storage_csv) storage_reader = csv.DictReader(storage_csv)
# for row in storage_reader: for row in storage_reader:
# if row['original']: if row['original']:
# Storage.objects.get_or_create(**row) Storage.objects.get_or_create(**row)
with open('./course/vertex.csv') as vertex_csv: with open('./course/vertex.csv') as vertex_csv:
vertex_reader = csv.DictReader(vertex_csv) vertex_reader = csv.DictReader(vertex_csv)
@ -59,8 +59,6 @@ if __name__ == '__main__':
sort = 0 sort = 0
for vertex in Vertex.objects.filter(course=course, content_type__model='topic').order_by("object_id"): for vertex in Vertex.objects.filter(course=course, content_type__model='topic').order_by("object_id"):
PivotVertex.objects.create(map_course=map_obj, vertex=vertex, sort=sort)
sort += 1
for small_vertex in Vertex.objects.filter(course=course, content_type__model='tutorial', vertex=vertex).order_by("object_id"): for small_vertex in Vertex.objects.filter(course=course, content_type__model='tutorial', vertex=vertex).order_by("object_id"):
PivotVertex.objects.create(map_course=map_obj, vertex=small_vertex, sort=sort) PivotVertex.objects.create(map_course=map_obj, vertex=small_vertex, sort=sort)
sort += 1 sort += 1
@ -68,6 +66,9 @@ if __name__ == '__main__':
PivotVertex.objects.create(map_course=map_obj, vertex=small_vertex, sort=sort) PivotVertex.objects.create(map_course=map_obj, vertex=small_vertex, sort=sort)
sort += 1 sort += 1
PivotVertex.objects.create(map_course=map_obj, vertex=vertex, sort=sort)
sort += 1
PivotCourseMap.objects.create(map_course=map_obj, route=route_obj, sort=0) PivotCourseMap.objects.create(map_course=map_obj, route=route_obj, sort=0)
course.save() course.save()

@ -5,7 +5,7 @@ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings")
django.setup() django.setup()
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from access.models import Progress from access.models.other import Progress
from courses.models import Vertex, Course from courses.models import Vertex, Course
if __name__ == '__main__': if __name__ == '__main__':

@ -30,7 +30,7 @@ if __name__ == '__main__':
child_thread, is_create = Thread.objects.get_or_create( child_thread, is_create = Thread.objects.get_or_create(
key="""user_%s__vertex_%s""" % (user.id, vertex.id,), key="""user_%s__vertex_%s""" % (user.id, vertex.id,),
text="""Домашняя работа по курсу %s и теме %s для студента %s""" % text="""%s - %s - %s""" %
(vertex.course.title, vertex.vertex_set.all()[0].title, user.get_full_name()), (vertex.course.title, vertex.vertex_set.all()[0].title, user.get_full_name()),
) )

@ -5,7 +5,7 @@ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings")
django.setup() django.setup()
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from access.models import Account from access.models.other import Account
if __name__ == '__main__': if __name__ == '__main__':
with open('./access/users.csv') as user_csv: with open('./access/users.csv') as user_csv:

@ -4,7 +4,7 @@ from django.dispatch import receiver
from yandex_money.models import Payment from yandex_money.models import Payment
from finance.models import Invoice from finance.models import Invoice
from access.models import Progress from access.models.other import Progress
@receiver(pre_save, sender=Invoice) @receiver(pre_save, sender=Invoice)

@ -67,6 +67,9 @@ def main_threads():
managers.groups.add(Group.objects.get(name='managers')) managers.groups.add(Group.objects.get(name='managers'))
managers.parent.add(lead_managers) managers.parent.add(lead_managers)
for user in get_user_model().objects.all():
Thread.objects.get_or_create(key="""user_%s""" % user.id)
if __name__ == '__main__': if __name__ == '__main__':
main_threads() main_threads()

@ -6,7 +6,7 @@ from rest_framework.response import Response
import csv import csv
from django.http import HttpResponse, HttpResponseForbidden from django.http import HttpResponse, HttpResponseForbidden
from access.models import Progress from access.models.other import Progress
from journals.models import Thread, Journal from journals.models import Thread, Journal
from journals.serilizers import ThreadDetailSerializer, ThreadAdminSerializer, JournalSerializer from journals.serilizers import ThreadDetailSerializer, ThreadAdminSerializer, JournalSerializer
from lms.tools import decode_base64 from lms.tools import decode_base64

@ -0,0 +1,20 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-12-01 20:12
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('maps', '0004_auto_20171129_1447'),
]
operations = [
migrations.AddField(
model_name='coursemap',
name='name',
field=models.CharField(default='Линейное прохождение', max_length=255, verbose_name='Имя прохождения'),
),
]

@ -16,11 +16,14 @@ class CourseRoute(models.Model):
return bool(sum([int(i.map_course.is_finish(user)) for i in self.pivotcoursemap_set.all()])) return bool(sum([int(i.map_course.is_finish(user)) for i in self.pivotcoursemap_set.all()]))
def get_active_objects(self, user): def get_active_objects(self, user):
return (i.map_course.getactive_object(user) for i in self.pivotcoursemap_set.all()) return (i.map_course.get_active_object(user) for i in self.pivotcoursemap_set.all())
def get_maps(self): def get_maps(self):
return (i.map_course for i in self.pivotcoursemap_set.all()) return (i.map_course for i in self.pivotcoursemap_set.all())
def get_first(self):
return self.pivotcoursemap_set.first().map_course
def __str__(self): def __str__(self):
return self.name return self.name
@ -34,10 +37,11 @@ class CourseMap(models.Model):
Способы отображения курса. Упорядочены в порядке возрастания приоретета. Способы отображения курса. Упорядочены в порядке возрастания приоретета.
""" """
course = models.ForeignKey(to='courses.Course', verbose_name='К какому курсу привязан') course = models.ForeignKey(to='courses.Course', verbose_name='К какому курсу привязан')
name = models.CharField(max_length=255, verbose_name="Имя прохождения", default="Линейное прохождение")
@transaction_decorator @transaction_decorator
def add_vertex(self, vertex, sort): def add_vertex(self, vertex, sort):
if sort > self.pivotvertex_set.count()+1: if sort > self.pivotvertex_set.count() + 1:
raise ValueError("list index out of range") raise ValueError("list index out of range")
for i in self.pivotvertex_set.filter(sort__gte=sort): for i in self.pivotvertex_set.filter(sort__gte=sort):
i.sort += 1 i.sort += 1
@ -48,23 +52,42 @@ class CourseMap(models.Model):
return pivot return pivot
def get_objects(self, vertex=None): def get_objects(self, vertex=None):
if not self.course == vertex.course: if vertex and not self.course == vertex.course:
raise MapTypeError('''Переданный узел принадлежит курсу "%s", а должен принадлежать курсу "%s"''' raise MapTypeError('''Переданный узел принадлежит курсу "%s", а должен принадлежать курсу "%s"'''
% (self.course.title, vertex.course.title)) % (self.course.title, vertex.course.title))
full_list = [i.vertex for i in self.pivotvertex_set.all()] full_list = [i.vertex for i in self.pivotvertex_set.all()]
if vertex: if vertex:
return full_list[:full_list.index(vertex)+1] return full_list[:full_list.index(vertex) + 1]
return full_list return full_list
def get_tree(self, serializer=None):
from courses.serializers import MiniVertexSerializer
serializer = serializer if serializer is not None else MiniVertexSerializer
def helper(v_list):
new_list = []
for i in v_list:
val = serializer(i).data
new_list.append(val)
if i.children.all().count():
val['children'] = helper(i.children.all())
return new_list
return helper([i.vertex for i in self.pivotvertex_set.filter(vertex__vertex__isnull=True)])
def get_difference(self, user) -> list: def get_difference(self, user) -> list:
return list(set([i.vertex for i in self.pivotvertex_set.all()]) return list(set([i.vertex for i in self.pivotvertex_set.all()])
.difference(set(user.progress_set.get(course=self.course).progress_list.all()))) .difference(set(user.progress_set.get(course=self.course).progress_list.all())))
def is_finish(self, user) -> bool: def is_finish(self, user) -> bool:
return self.get_difference(user) == [] return self.get_difference(user) == []
def get_active_object(self, user): def get_active_object(self, user):
return self.pivotvertex_set.exclude(vertex__in=self.get_difference(user))[0] return self.pivotvertex_set.exclude(vertex__in=self.get_difference(user), vertex__content_type__model='topic')[
0].vertex
def __str__(self): def __str__(self):
return '''Линейное прохождение по курсу "%s"''' % self.course.title return '''Линейное прохождение по курсу "%s"''' % self.course.title
@ -77,7 +100,8 @@ class CourseMap(models.Model):
class PivotCourseMap(models.Model): class PivotCourseMap(models.Model):
route = models.ForeignKey(to=CourseRoute, verbose_name="К какому узлу") route = models.ForeignKey(to=CourseRoute, verbose_name="К какому узлу")
sort = models.SmallIntegerField(verbose_name='Порядок сортировки') sort = models.SmallIntegerField(verbose_name='Порядок сортировки')
map_course = models.ForeignKey(to=CourseMap, verbose_name='К какой сортеровке имеетотношение', blank=True, null=True) map_course = models.ForeignKey(to=CourseMap, verbose_name='К какой сортеровке имеетотношение', blank=True,
null=True)
def __str__(self): def __str__(self):
return '''Карта с №%s по маршруту ID%s''' % (self.sort, self.route_id) return '''Карта с №%s по маршруту ID%s''' % (self.sort, self.route_id)
@ -85,14 +109,15 @@ class PivotCourseMap(models.Model):
class Meta: class Meta:
verbose_name = 'Порядок сортировки маршрута' verbose_name = 'Порядок сортировки маршрута'
verbose_name_plural = 'Порядки сортировок маршрутов' verbose_name_plural = 'Порядки сортировок маршрутов'
unique_together = (('map_course', 'route'), ('sort', 'route'), ) unique_together = (('map_course', 'route'), ('sort', 'route'),)
ordering = ('sort', ) ordering = ('sort',)
class PivotVertex(models.Model): class PivotVertex(models.Model):
vertex = models.ForeignKey(to='courses.Vertex', verbose_name="К какому узлу") vertex = models.ForeignKey(to='courses.Vertex', verbose_name="К какому узлу")
sort = models.SmallIntegerField(verbose_name='Порядок сортировки') sort = models.SmallIntegerField(verbose_name='Порядок сортировки')
map_course = models.ForeignKey(to=CourseMap, verbose_name='К какой сортеровке имеетотношение', blank=True, null=True) map_course = models.ForeignKey(to=CourseMap, verbose_name='К какой сортеровке имеетотношение', blank=True,
null=True)
def __str__(self): def __str__(self):
return '''Карта с №%s по линейному прохождению ID%s''' % (self.sort, self.map_course_id) return '''Карта с №%s по линейному прохождению ID%s''' % (self.sort, self.map_course_id)
@ -101,4 +126,4 @@ class PivotVertex(models.Model):
verbose_name = 'Порядок сортировки узла' verbose_name = 'Порядок сортировки узла'
verbose_name_plural = 'Порядки сортировок узла' verbose_name_plural = 'Порядки сортировок узла'
unique_together = (('map_course', 'vertex'), ('sort', 'map_course')) unique_together = (('map_course', 'vertex'), ('sort', 'map_course'))
ordering = ('sort', ) ordering = ('sort',)

@ -8,20 +8,30 @@ class CourseRouteSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = CourseRoute model = CourseRoute
fields = '__all__' fields = ('maps', 'name')
@staticmethod @staticmethod
def get_maps(self): def get_maps(self):
return [CourseMapSerializer(i).data for i in self.get_maps()] return [CourseMapSerializer(i).data for i in self.get_maps()][0]
class CourseMapSerializer(serializers.ModelSerializer): class CourseMapSerializer(serializers.ModelSerializer):
vertexes = serializers.SerializerMethodField() tree = serializers.SerializerMethodField()
course_slug = serializers.SerializerMethodField()
map_name = serializers.SerializerMethodField()
class Meta: class Meta:
model = CourseMap model = CourseMap
fields = '__all__' fields = ('tree', 'course_slug', 'map_name')
@staticmethod @staticmethod
def get_vertexes(self): def get_tree(self):
return [i.id for i in self.pivotvertex_set.all()] return self.get_tree()
@staticmethod
def get_course_slug(self):
return self.course.slug
@staticmethod
def get_map_name(self):
return self.name
Loading…
Cancel
Save