threads update

feature/fix_generate_pass
Andrey 8 years ago
parent 554c1b8c6c
commit 01b6d3b5fe
  1. 3
      access/admin.py
  2. 14
      access/migrations/0001_initial.py
  3. 35
      access/migrations/0002_auto_20171128_1150.py
  4. 41
      access/models.py
  5. 10
      access/serializers.py
  6. 10
      access/views.py
  7. 58
      courses/migrations/0001_initial.py
  8. 104
      courses/models.py
  9. 3
      courses/views.py
  10. 4
      finance/migrations/0001_initial.py
  11. 22
      finance/migrations/0002_invoice_yandex_pay.py
  12. 6
      journals/migrations/0001_initial.py
  13. 2
      library/migrations/0001_initial.py
  14. 6
      storage/migrations/0001_initial.py

@ -1,8 +1,7 @@
from django.contrib import admin from django.contrib import admin
from access.models import Progress, ExtraPrivilege, User, Account, Invite from access.models import Progress, User, Account, Invite
admin.site.register(User) admin.site.register(User)
admin.site.register(Account) admin.site.register(Account)
admin.site.register(ExtraPrivilege)
admin.site.register(Progress) admin.site.register(Progress)
admin.site.register(Invite) admin.site.register(Invite)

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-22 11:24 # Generated by Django 1.11.6 on 2017-11-28 11:50
from __future__ import unicode_literals from __future__ import unicode_literals
import access.models import access.models
@ -52,17 +52,6 @@ class Migration(migrations.Migration):
'verbose_name_plural': 'Дополнительная информация о пользователе', 'verbose_name_plural': 'Дополнительная информация о пользователе',
}, },
), ),
migrations.CreateModel(
name='ExtraPrivilege',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_done', models.BooleanField(default=False, verbose_name='Выполнено?')),
],
options={
'verbose_name': 'Доп право',
'verbose_name_plural': 'Доп права пользователя',
},
),
migrations.CreateModel( migrations.CreateModel(
name='Invite', name='Invite',
fields=[ fields=[
@ -79,7 +68,6 @@ class Migration(migrations.Migration):
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')),
('success', models.BooleanField(default=False, verbose_name='Завершён ли курс')),
], ],
options={ options={
'verbose_name': 'Прогресс пользователя', 'verbose_name': 'Прогресс пользователя',

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-22 11:24 # Generated by Django 1.11.6 on 2017-11-28 11:50
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
@ -12,46 +12,41 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('courses', '0001_initial'),
('access', '0001_initial'),
('auth', '0008_alter_user_username_max_length'), ('auth', '0008_alter_user_username_max_length'),
('access', '0001_initial'),
('courses', '0001_initial'),
] ]
operations = [ operations = [
migrations.AddField( migrations.AddField(
model_name='progress', model_name='progress',
name='active_obj', name='course',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.Vertex', verbose_name='Активный объект'), field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='Курс'),
), ),
migrations.AddField( migrations.AddField(
model_name='progress', model_name='progress',
name='course', name='progress_list',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='Курс'), 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='courses.CourseRoute', verbose_name='Шаблон для прохождения если не указан явно смотри функцию get_template()'),
), ),
migrations.AddField( migrations.AddField(
model_name='progress', model_name='progress',
name='user', name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент'), field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Студент'),
), ),
migrations.AddField( migrations.AddField(
model_name='invite', model_name='invite',
name='owner', name='owner',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
),
migrations.AddField(
model_name='extraprivilege',
name='subject',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Vertex', verbose_name='Объект'),
),
migrations.AddField(
model_name='extraprivilege',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL, verbose_name='Правообладатель'),
), ),
migrations.AddField( migrations.AddField(
model_name='account', model_name='account',
name='owner', name='owner',
field=models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
), ),
migrations.AddField( migrations.AddField(
model_name='user', model_name='user',

@ -5,7 +5,7 @@ import string
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django_celery_results.models import TaskResult from django_celery_results.models import TaskResult
from courses.models import Vertex, Course from courses.models import Vertex, Course, CourseMap, CourseRoute
from storage.models import Storage from storage.models import Storage
from django.core.mail import send_mail from django.core.mail import send_mail
@ -22,7 +22,7 @@ from journals.models import Journal, Thread, ACTION_CHOICES
class Invite(models.Model): class Invite(models.Model):
owner = models.OneToOneField(to=settings.AUTH_USER_MODEL) owner = models.OneToOneField(to=settings.AUTH_USER_MODEL, null=True)
hash = models.CharField(max_length=15) hash = models.CharField(max_length=15)
date = models.DateTimeField(null=True, blank=True) date = models.DateTimeField(null=True, blank=True)
@ -40,7 +40,7 @@ class Account(models.Model):
b_day = models.DateField(blank=True, null=True) b_day = models.DateField(blank=True, null=True)
city = models.CharField(max_length=63, null=True, blank=True) city = models.CharField(max_length=63, null=True, blank=True)
gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0) gender = models.SmallIntegerField(choices=GENDER_CHOICES, default=0)
owner = models.OneToOneField(to=settings.AUTH_USER_MODEL) 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/') 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) phone = models.CharField(max_length=15, null=True, blank=True)
@ -173,32 +173,33 @@ class User(AbstractBaseUser, PermissionsMixin):
class Progress(models.Model): class Progress(models.Model):
user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='Студент') user = models.OneToOneField(to=settings.AUTH_USER_MODEL, verbose_name='Студент', null=True)
course = models.ForeignKey(to=Course, verbose_name='Курс') course = models.OneToOneField(to=Course, verbose_name='Курс', null=True)
active_obj = models.ForeignKey(to=Vertex, verbose_name='Активный объект', blank=True, null=True) progress_list = models.ManyToManyField(to=Vertex, verbose_name='Лист пройденных объектов', blank=True)
success = models.BooleanField(default=False, verbose_name='Завершён ли курс') template = models.OneToOneField(to=CourseRoute, blank=True, null=True, verbose_name='Шаблон для прохождения если '
'не указан явно смотри '
'функцию get_template()')
def __str__(self): def __str__(self):
return '%s %s %s' % ( return '%s %s %s' % (
self.user.email, self.user.email,
('завершил курс' if self.success else 'в процессе изучения курса'), ('завершил курс' if self.is_finish() else 'в процессе изучения курса'),
self.course.title, self.course.title,
) )
def is_access(self, vertex): def get_template(self):
return not vertex.is_more(self.active_obj) return self.template if self.template else self.course.route
class Meta: def is_finish(self):
verbose_name = 'Прогресс пользователя' return self.get_template().is_finish(self.user)
verbose_name_plural = 'Прогресс пользователя'
unique_together = ("user", "course")
def get_objects_in_progress(self):
return self.get_template().get_active_objects(self.user)
class ExtraPrivilege(models.Model): def is_access(self, vertex):
user = models.ForeignKey(to=settings.AUTH_USER_MODEL, verbose_name='Правообладатель') return vertex in self.progress_list
is_done = models.BooleanField(default=False, verbose_name='Выполнено?')
subject = models.ForeignKey(to=Vertex, verbose_name='Объект')
class Meta: class Meta:
verbose_name = 'Доп право' verbose_name = 'Прогресс пользователя'
verbose_name_plural = 'Доп права пользователя' verbose_name_plural = 'Прогресс пользователя'
unique_together = (("user", "course"),)

@ -1,6 +1,6 @@
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 ExtraPrivilege, Account, Progress from access.models import Account, Progress
from courses.serializers import MiniVertexSerializer from courses.serializers import MiniVertexSerializer
@ -101,10 +101,4 @@ class UserSearchSerializer(serializers.ModelSerializer):
@staticmethod @staticmethod
def get_pay(self): def get_pay(self):
return sum([i.get_full_price() for i in self.bill_user.all()]) return sum([i.get_full_price() for i in self.bill_user.all()])
class ExtraPrivilegeSerializer(serializers.ModelSerializer):
class Meta:
model = ExtraPrivilege
exclude = ('user', )

@ -7,7 +7,7 @@ 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, ExtraPrivilege from access.models import Invite, Progress
from access.serializers import UserInitSerializer, UserSearchSerializer, UserProfileSerializer from access.serializers import UserInitSerializer, UserSearchSerializer, UserProfileSerializer
from courses.models import Vertex from courses.models import Vertex
from journals.models import Thread from journals.models import Thread
@ -232,13 +232,7 @@ class UpdateProgress(APIView):
except Progress.DoesNotExist: except Progress.DoesNotExist:
pass pass
try: return Response({'id': next_vertex.id, 'type': next_vertex.content_type.model}, status=200)
privilege = ExtraPrivilege.objects.get(user=request.user, subject=vertex)
privilege.is_done = True
privilege.save()
return Response({'id': next_vertex.id, 'type': next_vertex.content_type.model}, status=200)
except ExtraPrivilege.DoesNotExist:
return res_403
class UserGuardView(APIView): class UserGuardView(APIView):

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-22 11:24 # Generated by Django 1.11.6 on 2017-11-28 11:50
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
@ -12,9 +12,9 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('contenttypes', '0002_remove_content_type_name'),
('storage', '0001_initial'), ('storage', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('contenttypes', '0002_remove_content_type_name'),
] ]
operations = [ operations = [
@ -44,7 +44,6 @@ class Migration(migrations.Migration):
('big_image', models.URLField(blank=True, max_length=255, verbose_name='Большое изображение')), ('big_image', models.URLField(blank=True, max_length=255, verbose_name='Большое изображение')),
('big_mobile_image', models.URLField(blank=True, help_text='Большая картинка для мобильной версии', max_length=255, null=True, verbose_name='Под мобилку')), ('big_mobile_image', models.URLField(blank=True, help_text='Большая картинка для мобильной версии', max_length=255, null=True, verbose_name='Под мобилку')),
('mentors', models.ManyToManyField(blank=True, related_name='course_mentors', to=settings.AUTH_USER_MODEL, verbose_name='Кураторы')), ('mentors', models.ManyToManyField(blank=True, related_name='course_mentors', to=settings.AUTH_USER_MODEL, verbose_name='Кураторы')),
('teachers', models.ManyToManyField(related_name='course_teachers', to=settings.AUTH_USER_MODEL, verbose_name='Преподаватели')),
], ],
options={ options={
'verbose_name': 'Курс', 'verbose_name': 'Курс',
@ -55,10 +54,25 @@ class Migration(migrations.Migration):
name='CourseMap', name='CourseMap',
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')),
('dependent_elements', models.TextField(default='[]')), ('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Course', verbose_name='К какому курсу привязан')),
('independent_elements', models.TextField(default='[]')),
('course', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to='courses.Course')),
], ],
options={
'verbose_name': 'Карта линейного прохождения курсов',
'verbose_name_plural': 'Карты линейного прохождения курсов',
},
),
migrations.CreateModel(
name='CourseRoute',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(blank=True, max_length=255, null=True, unique=True, verbose_name='Имя шаблона')),
('is_template', models.BooleanField(default=True, verbose_name='Может ли быть использован как шаблон')),
('maps', models.ManyToManyField(to='courses.CourseMap', verbose_name='Карта линейного прохождения курсов')),
],
options={
'verbose_name': 'Маршрут прохождения',
'verbose_name_plural': 'Маршруты прохождения',
},
), ),
migrations.CreateModel( migrations.CreateModel(
name='Diploma', name='Diploma',
@ -83,6 +97,19 @@ class Migration(migrations.Migration):
'verbose_name_plural': 'Генераторы дипловов', 'verbose_name_plural': 'Генераторы дипловов',
}, },
), ),
migrations.CreateModel(
name='PivotVertex',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('sort', models.SmallIntegerField(unique=True, verbose_name='Порядок сортировки')),
('map_course', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.CourseMap', verbose_name='К какой сортеровке имеетотношение')),
],
options={
'verbose_name': 'Порядок сортировки узла',
'verbose_name_plural': 'Порядки сортировок узла',
'ordering': ('sort',),
},
),
migrations.CreateModel( migrations.CreateModel(
name='SkillJ', name='SkillJ',
fields=[ fields=[
@ -154,6 +181,11 @@ class Migration(migrations.Migration):
name='skill', name='skill',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Skills', verbose_name='Навык'), field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Skills', verbose_name='Навык'),
), ),
migrations.AddField(
model_name='pivotvertex',
name='vertex',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.Vertex', verbose_name='К какому узлу'),
),
migrations.AddField( migrations.AddField(
model_name='diploma', model_name='diploma',
name='template', name='template',
@ -164,6 +196,16 @@ class Migration(migrations.Migration):
name='user', name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
), ),
migrations.AddField(
model_name='course',
name='route',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.CourseRoute', verbose_name='Порядок прохождения по умолчанию'),
),
migrations.AddField(
model_name='course',
name='teachers',
field=models.ManyToManyField(related_name='course_teachers', to=settings.AUTH_USER_MODEL, verbose_name='Преподаватели'),
),
migrations.AddField( migrations.AddField(
model_name='achievements', model_name='achievements',
name='course', name='course',
@ -174,4 +216,8 @@ class Migration(migrations.Migration):
name='user', name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL), field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL),
), ),
migrations.AlterUniqueTogether(
name='pivotvertex',
unique_together=set([('map_course', 'vertex')]),
),
] ]

@ -91,6 +91,7 @@ class Course(models.Model):
help_text='Большая картинка для мобильной версии', max_length=255) help_text='Большая картинка для мобильной версии', max_length=255)
teachers = models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name='Преподаватели', teachers = models.ManyToManyField(to=settings.AUTH_USER_MODEL, verbose_name='Преподаватели',
related_name='course_teachers') related_name='course_teachers')
route = models.OneToOneField(to="CourseRoute", verbose_name="Порядок прохождения по умолчанию", blank=True, null=True)
def __str__(self): def __str__(self):
return self.title return self.title
@ -144,7 +145,7 @@ class Course(models.Model):
if i not in ['topic', 'tutorial', 'task']: if i not in ['topic', 'tutorial', 'task']:
raise ValueError('undefined model: ' + i) raise ValueError('undefined model: ' + i)
vertex = Vertex.objects.get(id=self.coursemap.get_first()) vertex = Vertex.objects.get(id=self.coursemap_set.get(sort=0).get_first())
if vertex.content_type.model in vertex_model_list: if vertex.content_type.model in vertex_model_list:
return vertex return vertex
@ -160,7 +161,7 @@ class Course(models.Model):
if i not in ['topic', 'tutorial', 'task']: if i not in ['topic', 'tutorial', 'task']:
raise ValueError('undefined model: ' + i) raise ValueError('undefined model: ' + i)
vertex = Vertex.objects.get(id=self.coursemap.get_last()) vertex = Vertex.objects.get(id=self.coursemap_set.get(sort=0).get_last())
if vertex.content_type.model in vertex_model_list: if vertex.content_type.model in vertex_model_list:
return vertex return vertex
@ -334,9 +335,6 @@ class Vertex(models.Model):
if not user.is_authenticated: if not user.is_authenticated:
return False return False
if self.extraprivilege_set.filter(user=user).exists():
return True
try: try:
progress = self.course.progress_set.get(user=user) progress = self.course.progress_set.get(user=user)
except ObjectDoesNotExist: except ObjectDoesNotExist:
@ -388,58 +386,80 @@ class Task(models.Model):
Материалы для урока по сути FileField, нужна только для создания лишней связи в таблице Материалы для урока по сути FileField, нужна только для создания лишней связи в таблице
и дублирования метазаголовков файла и дублирования метазаголовков файла
""" """
materials = models.ManyToManyField(Storage, verbose_name=u'Материалы для домашней работы', blank=True) materials = models.ManyToManyField(Storage, verbose_name='Материалы для домашней работы', blank=True)
is_exam = models.BooleanField(default=False, verbose_name=u'Экзамен или домашка') is_exam = models.BooleanField(default=False, verbose_name='Экзамен или домашка')
class Topic(models.Model): class Topic(models.Model):
""" """
Модель темы, нужно просто для объединения тасков и уроков. Модель темы, нужно просто для объединения тасков и уроков.
У некоторых тем есть иконка. У некоторых тем есть иконка.
Возможно поле icon перекачует в Vertex, а данная модель отвалится за ненадобностью Возможно поле icon перекачует в Vertex, а данная модель отвалится за ненадобностью
"""
icon = models.ImageField(verbose_name='Иконка темы', null=True, blank=True)
class CourseRoute(models.Model):
"""
Объединение нескольких мап курса, одназначно
определяет способ прохождения по курсу.
""" """
icon = models.ImageField(verbose_name=u'Иконка темы', null=True, blank=True) name = models.CharField(max_length=255, verbose_name='Имя шаблона', blank=True, null=True, unique=True)
maps = models.ManyToManyField(to="CourseMap", verbose_name="Карта линейного прохождения курсов")
is_template = models.BooleanField(default=True, verbose_name='Может ли быть использован как шаблон')
def is_finish(self, user):
return bool(sum([int(i.is_finish(user)) for i in self.maps.all()]))
def get_active_objects(self, user):
return [i.getactive_object(user) for i in self.maps.all()]
class Meta:
verbose_name = 'Маршрут прохождения'
verbose_name_plural = 'Маршруты прохождения'
class CourseMap(models.Model): class CourseMap(models.Model):
""" """
Так как курс евляется связным графом мы можем отобразить его бесконечным количеством способов, Способы отображения курса. Упорядочены в порядке возрастания приоретета.
а нам нужен один самый красивый, мы должный в явном виде указать способ отображения.
""" """
course = models.OneToOneField(to=Course) course = models.ForeignKey(to=Course, verbose_name='К какому курсу привязан')
dependent_elements = models.TextField(default='[]')
independent_elements = models.TextField(default='[]')
def map_to_list(self) -> list: @transaction_decorator
def helper(root_list): def add_vertex(self, vertex, sort):
res = [] if sort > self.pivotvertex_set.count()+1:
for i in root_list: raise ValueError("list index out of range")
if type(i) == type([]): for i in self.pivotvertex_set.filter(sort__gte=sort):
res += helper(i) i.sort += 1
i.save()
else: pivot = PivotVertex.objects.create(vertex=vertex, sort=sort, map_course=self)
res.append(i) pivot.save()
return pivot
return res 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 helper(json.loads(self.dependent_elements)) def is_finish(self, user) -> bool:
return self.get_difference(user) == []
def get_next(self, vertex_id) -> int: def get_active_object(self, user):
res_list = self.map_to_list() return self.pivotvertex_set.exclude(vertex__in=self.get_difference(user))[0]
if not res_list[-1] == vertex_id:
return res_list[res_list.index(vertex_id) + 1] class Meta:
error = "vertex_id " + str(vertex_id) + " last object in list\n" + ",".join([str(v) for v in res_list]) verbose_name = 'Карта линейного прохождения курсов'
raise ValueError(error) verbose_name_plural = 'Карты линейного прохождения курсов'
def get_previous(self, vertex_id) -> int:
res_list = self.map_to_list()
if not res_list[0] == vertex_id:
return res_list[res_list.index(vertex_id) - 1]
error = "vertex_id " + str(vertex_id) + " first object in list\n" + ",".join([str(v) for v in res_list])
raise ValueError(error)
def get_first(self): class PivotVertex(models.Model):
return self.map_to_list()[0] vertex = models.ForeignKey(to=Vertex, verbose_name="К какому узлу")
sort = models.SmallIntegerField(verbose_name='Порядок сортировки', unique=True)
map_course = models.ForeignKey(to=CourseMap, verbose_name='К какой сортеровке имеетотношение', blank=True, null=True)
def get_last(self): class Meta:
return self.map_to_list()[-1] verbose_name = 'Порядок сортировки узла'
verbose_name_plural = 'Порядки сортировок узла'
unique_together = (('map_course', 'vertex'),)
ordering = ('sort', )

@ -2,9 +2,8 @@ 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 ExtraPrivilegeSerializer
from courses.models import Course, Vertex from courses.models import Course, Vertex
from access.models import Progress, ExtraPrivilege from access.models import Progress
from courses.serializers import CourseDetailSerializer, CourseListSerializer, VertexSerializer, CourseTreeSerializer from courses.serializers import CourseDetailSerializer, CourseListSerializer, VertexSerializer, CourseTreeSerializer
from journals.models import Thread from journals.models import Thread

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-22 11:33 # Generated by Django 1.11.6 on 2017-11-28 11:50
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
@ -12,6 +12,7 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('yandex_money', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('courses', '0001_initial'), ('courses', '0001_initial'),
] ]
@ -45,6 +46,7 @@ class Migration(migrations.Migration):
('is_open', models.BooleanField(default=True, verbose_name='Открывает ли платёж курс')), ('is_open', models.BooleanField(default=True, verbose_name='Открывает ли платёж курс')),
('date', models.DateTimeField(auto_now_add=True)), ('date', models.DateTimeField(auto_now_add=True)),
('bill', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='finance.Bill', verbose_name='Связный счёт')), ('bill', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='finance.Bill', verbose_name='Связный счёт')),
('yandex_pay', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='yandex_money.Payment')),
], ],
options={ options={
'verbose_name': 'Платёж', 'verbose_name': 'Платёж',

@ -1,22 +0,0 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-22 11:33
from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('yandex_money', '0001_initial'),
('finance', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='invoice',
name='yandex_pay',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='yandex_money.Payment'),
),
]

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-22 11:24 # Generated by Django 1.11.6 on 2017-11-28 11:50
from __future__ import unicode_literals from __future__ import unicode_literals
from django.conf import settings from django.conf import settings
@ -12,10 +12,10 @@ class Migration(migrations.Migration):
initial = True initial = True
dependencies = [ dependencies = [
('auth', '0008_alter_user_username_max_length'),
('contenttypes', '0002_remove_content_type_name'),
('storage', '0001_initial'), ('storage', '0001_initial'),
migrations.swappable_dependency(settings.AUTH_USER_MODEL), migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('contenttypes', '0002_remove_content_type_name'),
('auth', '0008_alter_user_username_max_length'),
] ]
operations = [ operations = [

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-22 11:24 # Generated by Django 1.11.6 on 2017-11-28 11:50
from __future__ import unicode_literals from __future__ import unicode_literals
import datetime import datetime

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# Generated by Django 1.11.6 on 2017-11-22 11:24 # Generated by Django 1.11.6 on 2017-11-28 11:50
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models from django.db import migrations, models
@ -17,8 +17,8 @@ class Migration(migrations.Migration):
name='Storage', name='Storage',
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')),
('original', models.FileField(upload_to='files', verbose_name='Файл')), ('original', models.FileField(max_length=255, upload_to='files', verbose_name='Файл')),
('name', models.CharField(blank=True, max_length=63, null=True, verbose_name='Видимое имя файла')), ('name', models.CharField(blank=True, max_length=255, null=True, verbose_name='Видимое имя файла')),
], ],
options={ options={
'verbose_name': 'Файл', 'verbose_name': 'Файл',

Loading…
Cancel
Save