feature/fix_generate_pass
Andrey 8 years ago
parent 14ad75259b
commit c43e5830d0
  1. 66
      access/migrations/0002_auto_20171128_1518.py
  2. 27
      access/migrations/0003_auto_20171129_1639.py
  3. 7
      access/models.py
  4. 14
      access/serializers.py
  5. 31
      courses/models.py
  6. 9
      courses/serializers.py
  7. 13
      courses/views.py
  8. 10304
      csv/access/account.csv
  9. 6038
      csv/access/progress.csv
  10. 11074
      csv/access/users.csv
  11. 39
      csv/load_courses.py
  12. 40
      csv/load_perm.py
  13. 8
      finance/views.py
  14. 4
      maps/admin.py
  15. 3
      maps/apps.py
  16. 2
      maps/exeptions.py
  17. 24
      maps/migrations/0002_auto_20171129_1439.py
  18. 25
      maps/migrations/0003_auto_20171129_1441.py
  19. 19
      maps/migrations/0004_auto_20171129_1447.py
  20. 42
      maps/models.py
  21. 27
      maps/serializers.py

@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-28 15:18
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
('access', '0001_initial'),
('auth', '0008_alter_user_username_max_length'),
('maps', '0001_initial'),
('courses', '0002_auto_20171128_1518'),
]
operations = [
migrations.AddField(
model_name='progress',
name='course',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='Курс'),
),
migrations.AddField(
model_name='progress',
name='progress_list',
field=models.ManyToManyField(blank=True, to='courses.Vertex', verbose_name='Лист пройденных объектов'),
),
migrations.AddField(
model_name='progress',
name='template',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='maps.CourseRoute', verbose_name='Шаблон для прохождения если не указан явно смотри функцию get_template()'),
),
migrations.AddField(
model_name='progress',
name='user',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент'),
),
migrations.AddField(
model_name='invite',
name='owner',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='account',
name='owner',
field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='user',
name='groups',
field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.Group', verbose_name='groups'),
),
migrations.AddField(
model_name='user',
name='user_permissions',
field=models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.Permission', verbose_name='user permissions'),
),
migrations.AlterUniqueTogether(
name='progress',
unique_together=set([('user', 'course')]),
),
]

@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-29 16:39
from __future__ import unicode_literals
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('access', '0002_auto_20171128_1518'),
]
operations = [
migrations.AlterField(
model_name='progress',
name='course',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='Курс'),
),
migrations.AlterField(
model_name='progress',
name='user',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент'),
),
]

@ -174,17 +174,16 @@ class User(AbstractBaseUser, PermissionsMixin):
class Progress(models.Model):
user = models.OneToOneField(to=settings.AUTH_USER_MODEL, verbose_name='Студент', null=True)
course = models.OneToOneField(to=Course, verbose_name='Курс', null=True)
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 %s' % (
return '%s %s' % (
self.user.email,
('завершил курс' if self.is_finish() else 'в процессе изучения курса'),
self.course.title,
)

@ -1,18 +1,18 @@
from django.contrib.auth import get_user_model
from rest_framework import serializers
from access.models import Account, Progress
from courses.serializers import MiniVertexSerializer
from maps.serializers import CourseRouteSerializer
class ProgressSerializer(serializers.ModelSerializer):
vertex = serializers.SerializerMethodField()
template = serializers.SerializerMethodField()
course = serializers.SerializerMethodField()
max = serializers.SerializerMethodField()
number = serializers.SerializerMethodField()
class Meta:
model = Progress
fields = ('course', 'vertex', 'number', 'max')
fields = ('course', 'template', 'number', 'max', 'progress_list', )
@staticmethod
def get_max(self):
@ -20,17 +20,17 @@ class ProgressSerializer(serializers.ModelSerializer):
@staticmethod
def get_number(self):
if self.success:
if self.is_finish():
return self.get_max()
return self.active_obj.get_number('topic')
return self.progress_list.filter(content_type__model="topic").count()
@staticmethod
def get_course(self):
return {'title': self.course.title, 'slug': self.course.slug}
@staticmethod
def get_vertex(self):
return MiniVertexSerializer(self.active_obj).data
def get_template(self):
return CourseRouteSerializer(self.get_template()).data
class AccountSerializer(serializers.ModelSerializer):

@ -101,37 +101,14 @@ class Course(models.Model):
def get_teacher(self):
return random.choice(self.teachers.all())
def get_map(self, user):
route = self.route
if user.is_authenticated:
route = user.progress_set.get(course=self).get_template()
map_list = route.get_sorted_maps()
return self.route.maps.all()[0]
def get_tree(self, serializer):
"""
Способ отображения дочерних элементов.
Принимает на вход сериалайзер узла
"""
course_map = json.loads(CourseMap.objects.get(course=self).dependent_elements)
def helper(tree_id):
acc = []
for j, i in enumerate(tree_id):
if type([]) == type(i):
acc[-1]['children'] = helper(i)
else:
acc.append(serializer(Vertex.objects.get(id=i)).data)
return acc
return helper(course_map)
def get_maps(self, user):
return user.progress_set.get(course=self).get_template().get_maps()
def get_vertexes(self, vertex_type=None):
course_map = CourseMap.objects.get(course=self).map_to_list()
if vertex_type:
return self.vertex_set.filter(content_type__model=vertex_type, id__in=course_map)
return course_map
return self.vertex_set.filter(content_type__model=vertex_type, course=self)
return self.vertex_set.filter(course=self)
def get_statistic(self):
"""

@ -1,6 +1,7 @@
from rest_framework import serializers
from courses.models import Course, Vertex, Tutorial, Topic, Task
from maps.serializers import CourseRouteSerializer
class TutorialSerializer(serializers.ModelSerializer):
@ -84,15 +85,15 @@ class CourseListSerializer(serializers.ModelSerializer):
class CourseTreeSerializer(serializers.ModelSerializer):
children = serializers.SerializerMethodField()
route = serializers.SerializerMethodField()
class Meta:
model = Course
fields = ['id', 'children', 'title']
fields = ['id', 'route']
@staticmethod
def get_children(self):
return self.get_tree(MiniVertexSerializer)
def get_route(self):
return CourseRouteSerializer(self.route).data
class CourseDetailSerializer(serializers.ModelSerializer):

@ -2,6 +2,7 @@ from rest_framework.views import APIView
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from access.serializers import ProgressSerializer
from courses.models import Course, Vertex
from access.models import Progress
from courses.serializers import CourseDetailSerializer, CourseListSerializer, VertexSerializer, CourseTreeSerializer
@ -32,16 +33,12 @@ class TreeView(APIView):
return Response(res, self.status_code)
try:
res['active_id'] = Progress.objects.get(course=course, user=request.user).active_obj.id
res['progress'] = ProgressSerializer(
Progress.objects.get(course=course, user=request.user)
).data
except Progress.DoesNotExist:
res['active_id'] = False
res['progress'] = False
res['extra_privilege'] = [
ExtraPrivilegeSerializer(i).data for i in ExtraPrivilege.objects.filter(
user=request.user,
subject__course=course,
)
]
return Response(res, self.status_code)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -6,11 +6,15 @@ sys.path.append("../")
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "lms.settings")
django.setup()
from courses.models import Course, Vertex, CourseMap
from courses.models import Course, Vertex
from maps.models import CourseRoute, CourseMap, PivotVertex, PivotCourseMap
from storage.models import Storage
if __name__ == '__main__':
CourseMap.objects.all().delete()
CourseRoute.objects.all().delete()
PivotVertex.objects.all().delete()
PivotCourseMap.objects.all().delete()
Vertex.objects.all().delete()
Course.objects.all().delete()
with open('./course/course.csv') as user_csv:
@ -32,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)
@ -49,12 +53,21 @@ if __name__ == '__main__':
Vertex.objects.create_with_dependencies(model=model, course=course, parents=parents, **row)
for course in Course.objects.all():
map_obj = []
map_obj = CourseMap.objects.create(course=course)
route_obj = CourseRoute.objects.create(name='''Основной шаблон по курсу "%s"''' % course.title)
course.route = route_obj
sort = 0
for vertex in Vertex.objects.filter(course=course, content_type__model='topic').order_by("object_id"):
map_obj.append(vertex.id)
theme_map = []
for small_vertex in vertex.children.all().order_by("object_id"):
theme_map.append(small_vertex.id)
map_obj.append(theme_map)
CourseMap.objects.get_or_create(dependent_elements=map_obj, course=course)
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
for small_vertex in Vertex.objects.filter(course=course, content_type__model='task', vertex=vertex).order_by("object_id"):
PivotVertex.objects.create(map_course=map_obj, vertex=small_vertex, sort=sort)
sort += 1
PivotCourseMap.objects.create(map_course=map_obj, route=route_obj, sort=0)
course.save()

@ -13,40 +13,40 @@ if __name__ == '__main__':
with open('./access/progress.csv') as progress_csv:
progress_reader = csv.DictReader(progress_csv)
for row in progress_reader:
course = Course.objects.get(id=row['course'])
vertex = None
if row['type'] == 'lesson':
vertex = Vertex.objects.get(content_type__model='tutorial', object_id=row['last_success_obj'])
try:
if row['type'] == 'lesson':
vertex = Vertex.objects.get(content_type__model='tutorial', object_id=row['last_success_obj'],
course=course)
elif row['type'] == 'homework':
vertex = Vertex.objects.get(content_type__model='task', object_id=row['last_success_obj'])
elif row['type'] == 'homework':
vertex = Vertex.objects.get(content_type__model='task', object_id=row['last_success_obj'],
course=course)
elif row['type'] == 'exam':
get_id = int(row['last_success_obj'])+10000
vertex = Vertex.objects.get(content_type__model='task', object_id=str(get_id))
elif row['type'] == 'exam':
get_id = int(row['last_success_obj']) + 10000
vertex = Vertex.objects.get(content_type__model='task', object_id=str(get_id), course=course)
course = Course.objects.get(id=row['course'])
except Vertex.DoesNotExist:
pass
try:
if vertex and not vertex == course.get_last(['task', 'tutorial']):
Progress.objects.get_or_create(
if vertex is not None:
p, c = Progress.objects.get_or_create(
user=get_user_model().objects.get(id=row['user']),
course=course,
active_obj=vertex.get_next(['task', 'tutorial'])
)
obj_list = list(course.route.get_maps())[0].get_objects(vertex)
elif vertex and vertex == course.get_last(['task', 'tutorial']):
Progress.objects.get_or_create(
user=get_user_model().objects.get(id=row['user']),
course=course,
success=True
)
if c:
p.progress_list.add(*obj_list)
else:
Progress.objects.get_or_create(
p, c = Progress.objects.get_or_create(
user=get_user_model().objects.get(id=row['user']),
course=course,
active_obj=course.get_first(['task', 'tutorial'])
)
except get_user_model().DoesNotExist:
print(row['user'])
print(row['user'])

@ -39,13 +39,15 @@ class BillListView(APIView):
if bill:
bill['user'] = get_user_model().objects.get(email=bill['user'])
bill['opener'] = get_user_model().objects.get(email=bill['opener'])
bill['course'] = Course.objects.get(title=bill['course'][0])
bill['course'] = Course.objects.get(title=bill['course'])
bill.pop('invoices', None)
bill_obj, is_create = Bill.objects.update_or_create(**bill)
invoices = bill_obj.invoice_set.all()
for i in children:
i['method'] = get_real_name(elem=i['method'][0], array=Invoice.BILL_METHOD)
i['status'] = get_real_name(elem=i['status'][0], array=Invoice.BILL_STATUSES)
i['method'] = get_real_name(elem=i['method'], array=Invoice.BILL_METHOD)
i['status'] = get_real_name(elem=i['status'], array=Invoice.BILL_STATUSES)
i['bill'] = bill_obj
i['yandex_pay'] = None
invoice, _is_create = Invoice.objects.update_or_create(**i)

@ -1,6 +1,8 @@
from django.contrib import admin
from maps.models import CourseMap, CourseRoute
from maps.models import CourseMap, CourseRoute, PivotCourseMap, PivotVertex
admin.site.register(CourseMap)
admin.site.register(CourseRoute)
admin.site.register(PivotCourseMap)
admin.site.register(PivotVertex)

@ -2,4 +2,5 @@ from django.apps import AppConfig
class MapsConfig(AppConfig):
name = 'maps'
name = "maps"
verbose_name = "Отображение курсов"

@ -0,0 +1,2 @@
class MapTypeError(ValueError):
pass

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-29 14:39
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('courses', '0002_auto_20171128_1518'),
('maps', '0001_initial'),
]
operations = [
migrations.AlterUniqueTogether(
name='pivotcoursemap',
unique_together=set([('map_course', 'route'), ('sort', 'route')]),
),
migrations.AlterUniqueTogether(
name='pivotvertex',
unique_together=set([('sort', 'map_course'), ('map_course', 'vertex')]),
),
]

@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-29 14:41
from __future__ import unicode_literals
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('maps', '0002_auto_20171129_1439'),
]
operations = [
migrations.AlterField(
model_name='pivotcoursemap',
name='sort',
field=models.SmallIntegerField(verbose_name='Порядок сортировки'),
),
migrations.AlterField(
model_name='pivotvertex',
name='sort',
field=models.SmallIntegerField(verbose_name='Порядок сортировки'),
),
]

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-29 14:47
from __future__ import unicode_literals
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('maps', '0003_auto_20171129_1441'),
]
operations = [
migrations.AlterModelOptions(
name='pivotcoursemap',
options={'ordering': ('sort',), 'verbose_name': 'Порядок сортировки маршрута', 'verbose_name_plural': 'Порядки сортировок маршрутов'},
),
]

@ -1,6 +1,7 @@
from django.db import models
from lms.global_decorators import transaction_decorator
from maps.exeptions import MapTypeError
class CourseRoute(models.Model):
@ -17,9 +18,12 @@ class CourseRoute(models.Model):
def get_active_objects(self, user):
return (i.map_course.getactive_object(user) for i in self.pivotcoursemap_set.all())
def get_view(self):
def get_maps(self):
return (i.map_course for i in self.pivotcoursemap_set.all())
def __str__(self):
return self.name
class Meta:
verbose_name = 'Маршрут прохождения'
verbose_name_plural = 'Маршруты прохождения'
@ -43,13 +47,18 @@ class CourseMap(models.Model):
pivot.save()
return pivot
def merge(self, another):
return # TODO: Доделать!!!
def get_objects(self, vertex=None):
if not self.course == vertex.course:
raise MapTypeError('''Переданный узел принадлежит курсу "%s", а должен принадлежать курсу "%s"'''
% (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
def get_difference(self, user) -> list:
return list(set(
[i.vertex for i in self.pivotvertex_set.all()]).difference(set(user.progress.progress_list.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())))
def is_finish(self, user) -> bool:
return self.get_difference(user) == []
@ -57,6 +66,9 @@ class CourseMap(models.Model):
def get_active_object(self, user):
return self.pivotvertex_set.exclude(vertex__in=self.get_difference(user))[0]
def __str__(self):
return '''Линейное прохождение по курсу "%s"''' % self.course.title
class Meta:
verbose_name = 'Карта линейного прохождения курсов'
verbose_name_plural = 'Карты линейного прохождения курсов'
@ -64,23 +76,29 @@ class CourseMap(models.Model):
class PivotCourseMap(models.Model):
route = models.ForeignKey(to=CourseRoute, verbose_name="К какому узлу")
sort = models.SmallIntegerField(verbose_name='Порядок сортировки', unique=True)
sort = models.SmallIntegerField(verbose_name='Порядок сортировки')
map_course = models.ForeignKey(to=CourseMap, verbose_name='К какой сортеровке имеетотношение', blank=True, null=True)
def __str__(self):
return '''Карта с №%s по маршруту ID%s''' % (self.sort, self.route_id)
class Meta:
verbose_name = 'Порядок сортировки узла'
verbose_name_plural = 'Порядки сортировок узла'
unique_together = (('map_course', 'route'),)
verbose_name = 'Порядок сортировки маршрута'
verbose_name_plural = 'Порядки сортировок маршрутов'
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='Порядок сортировки', unique=True)
sort = models.SmallIntegerField(verbose_name='Порядок сортировки')
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)
class Meta:
verbose_name = 'Порядок сортировки узла'
verbose_name_plural = 'Порядки сортировок узла'
unique_together = (('map_course', 'vertex'),)
unique_together = (('map_course', 'vertex'), ('sort', 'map_course'))
ordering = ('sort', )

@ -0,0 +1,27 @@
from rest_framework import serializers
from maps.models import CourseRoute, CourseMap
class CourseRouteSerializer(serializers.ModelSerializer):
maps = serializers.SerializerMethodField()
class Meta:
model = CourseRoute
fields = '__all__'
@staticmethod
def get_maps(self):
return [CourseMapSerializer(i).data for i in self.get_maps()]
class CourseMapSerializer(serializers.ModelSerializer):
vertexes = serializers.SerializerMethodField()
class Meta:
model = CourseMap
fields = '__all__'
@staticmethod
def get_vertexes(self):
return [i.id for i in self.pivotvertex_set.all()]
Loading…
Cancel
Save