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 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(Account)

@ -5,6 +5,8 @@ from __future__ import unicode_literals
import access.models
from django.db import migrations, models
import access.models.user
class Migration(migrations.Migration):
@ -34,7 +36,7 @@ class Migration(migrations.Migration):
'verbose_name_plural': 'Пользователи',
},
managers=[
('objects', access.models.CustomUserManager()),
('objects', access.models.user.CustomUserManager()),
],
),
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 string
from django.contrib.contenttypes.models import ContentType
from django_celery_results.models import TaskResult
from courses.models import Vertex, Course
from maps.models import CourseMap, CourseRoute
from storage.models import Storage
from django.contrib.auth.base_user import BaseUserManager, AbstractBaseUser
from django.contrib.auth.models import Group, PermissionsMixin
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.conf import settings
from django.utils import timezone
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):
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 = 'Дополнительная информация о пользователе'
from access.models.other import Invite, Account
from journals.models import Thread
from lms.global_decorators import transaction_decorator
class CustomUserManager(BaseUserManager):
@ -170,36 +130,4 @@ class User(AbstractBaseUser, PermissionsMixin):
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
class Meta:
verbose_name = 'Прогресс пользователя'
verbose_name_plural = 'Прогресс пользователя'
unique_together = (("user", "course"),)
verbose_name_plural = _('Пользователи')

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

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

@ -61,6 +61,13 @@ class VertexSerializer(MiniVertexSerializer):
return False
class CourseInitSerializer(serializers.ModelSerializer):
class Meta:
model = Course
fields = ['title', 'slug']
class CourseListSerializer(serializers.ModelSerializer):
statistic = serializers.SerializerMethodField()
level = serializers.SerializerMethodField()
@ -84,18 +91,6 @@ class CourseListSerializer(serializers.ModelSerializer):
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):
level = serializers.SerializerMethodField()
direction = serializers.SerializerMethodField()

@ -2,10 +2,9 @@ from rest_framework.views import APIView
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from access.serializers import ProgressSerializer
from maps.serializers import CourseMapSerializer
from courses.models import Course, Vertex
from access.models import Progress
from courses.serializers import CourseDetailSerializer, CourseListSerializer, VertexSerializer, CourseTreeSerializer
from courses.serializers import CourseDetailSerializer, CourseListSerializer, VertexSerializer
from journals.models import Thread
@ -25,21 +24,11 @@ class TreeView(APIView):
except Course.DoesNotExist:
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():
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)
return Response(CourseMapSerializer(course.route.get_first()).data, self.status_code)
class CourseDetailView(APIView):
@ -69,14 +58,8 @@ class CourseListView(APIView):
course_list = Course.objects.all()
else:
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)

@ -36,11 +36,11 @@ if __name__ == '__main__':
except IntegrityError:
pass
# with open('./course/storage.csv') as storage_csv:
# storage_reader = csv.DictReader(storage_csv)
# for row in storage_reader:
# if row['original']:
# Storage.objects.get_or_create(**row)
with open('./course/storage.csv') as storage_csv:
storage_reader = csv.DictReader(storage_csv)
for row in storage_reader:
if row['original']:
Storage.objects.get_or_create(**row)
with open('./course/vertex.csv') as vertex_csv:
vertex_reader = csv.DictReader(vertex_csv)
@ -59,8 +59,6 @@ if __name__ == '__main__':
sort = 0
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"):
PivotVertex.objects.create(map_course=map_obj, vertex=small_vertex, sort=sort)
sort += 1
@ -68,6 +66,9 @@ if __name__ == '__main__':
PivotVertex.objects.create(map_course=map_obj, vertex=small_vertex, sort=sort)
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)
course.save()

@ -5,7 +5,7 @@ os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings")
django.setup()
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
if __name__ == '__main__':

@ -30,7 +30,7 @@ if __name__ == '__main__':
child_thread, is_create = Thread.objects.get_or_create(
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()),
)

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

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

@ -67,6 +67,9 @@ def main_threads():
managers.groups.add(Group.objects.get(name='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__':
main_threads()

@ -6,7 +6,7 @@ from rest_framework.response import Response
import csv
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.serilizers import ThreadDetailSerializer, ThreadAdminSerializer, JournalSerializer
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()]))
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):
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):
return self.name
@ -34,10 +37,11 @@ class CourseMap(models.Model):
Способы отображения курса. Упорядочены в порядке возрастания приоретета.
"""
course = models.ForeignKey(to='courses.Course', verbose_name='К какому курсу привязан')
name = models.CharField(max_length=255, verbose_name="Имя прохождения", default="Линейное прохождение")
@transaction_decorator
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")
for i in self.pivotvertex_set.filter(sort__gte=sort):
i.sort += 1
@ -48,23 +52,42 @@ class CourseMap(models.Model):
return pivot
def get_objects(self, vertex=None):
if not self.course == vertex.course:
if vertex and not self.course == vertex.course:
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()]
if vertex:
return full_list[:full_list.index(vertex)+1]
return full_list[:full_list.index(vertex) + 1]
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:
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:
return self.get_difference(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):
return '''Линейное прохождение по курсу "%s"''' % self.course.title
@ -77,7 +100,8 @@ class CourseMap(models.Model):
class PivotCourseMap(models.Model):
route = models.ForeignKey(to=CourseRoute, 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):
return '''Карта с №%s по маршруту ID%s''' % (self.sort, self.route_id)
@ -85,14 +109,15 @@ class PivotCourseMap(models.Model):
class Meta:
verbose_name = 'Порядок сортировки маршрута'
verbose_name_plural = 'Порядки сортировок маршрутов'
unique_together = (('map_course', 'route'), ('sort', 'route'), )
ordering = ('sort', )
unique_together = (('map_course', 'route'), ('sort', 'route'),)
ordering = ('sort',)
class PivotVertex(models.Model):
vertex = models.ForeignKey(to='courses.Vertex', 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):
return '''Карта с №%s по линейному прохождению ID%s''' % (self.sort, self.map_course_id)
@ -101,4 +126,4 @@ class PivotVertex(models.Model):
verbose_name = 'Порядок сортировки узла'
verbose_name_plural = 'Порядки сортировок узла'
unique_together = (('map_course', 'vertex'), ('sort', 'map_course'))
ordering = ('sort', )
ordering = ('sort',)

@ -8,20 +8,30 @@ class CourseRouteSerializer(serializers.ModelSerializer):
class Meta:
model = CourseRoute
fields = '__all__'
fields = ('maps', 'name')
@staticmethod
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):
vertexes = serializers.SerializerMethodField()
tree = serializers.SerializerMethodField()
course_slug = serializers.SerializerMethodField()
map_name = serializers.SerializerMethodField()
class Meta:
model = CourseMap
fields = '__all__'
fields = ('tree', 'course_slug', 'map_name')
@staticmethod
def get_vertexes(self):
return [i.id for i in self.pivotvertex_set.all()]
def get_tree(self):
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