# -*- coding: utf-8 -*- import uuid import unidecode from django.contrib.postgres.fields import ArrayField from django.db import models from django.template.defaultfilters import slugify from model_utils import Choices from lms.tools import get_real_name, get_empty_list COURSE_LEVEL = ( ('B', 'Базовый'), ('A', 'Продвинутый'), ('E', 'Экспертный'), ('B+A', 'Базовый + Продвинутый'), ) COURSE_DIRECTION = ( (3, 'Бизнес'), (2, 'Веб-дизайн'), (1, 'Разработка'), (4, 'Рисование'), (5, 'Музыка'), ) def upload_material(instance, filename): return '/'.join([ 'materials', str(instance.topic.course.token), str(instance.topic.id), str(instance.token), filename]) class Lesson(models.Model): token = models.UUIDField(verbose_name="Токен", default=uuid.uuid4, editable=False) key = models.UUIDField( verbose_name="Внутрений ключ используется для расшивровки", default=uuid.uuid4, editable=False) topic = models.ForeignKey(to="Topic", verbose_name='Тема') title = models.CharField(verbose_name='Название', max_length=255) description = models.TextField(verbose_name='Описание', blank=True, null=True) video = models.TextField(verbose_name='Код видео', blank=True, null=True) materials = ArrayField( models.FileField(verbose_name="Материал к уроку", upload_to=upload_material, max_length=255), verbose_name="Материалы к уроку", default=get_empty_list, ) material_tokens = ArrayField( models.UUIDField(verbose_name="Токен материала", editable=False), default=get_empty_list, verbose_name='Материалы курса', blank=True ) free = models.BooleanField(default=False, verbose_name='Привилегии для узла не будут проверяться') sort = models.SmallIntegerField(verbose_name='Поле сортировки') is_hm = models.BooleanField(default=False) #TODO костыли old_id = models.IntegerField(null=True, blank=True) def __str__(self): return self.title class Meta: verbose_name = "Урок" verbose_name_plural = "Уроки" ordering = ('sort', ) unique_together = ('sort', 'topic') class Topic(models.Model): course = models.ForeignKey(to="Course", verbose_name='курс') title = models.CharField(verbose_name='Название', max_length=255) sort = models.SmallIntegerField(verbose_name='Поле сортировки') def __str__(self): return self.title class Meta: verbose_name = "Тема" verbose_name_plural = "Темы" ordering = ('sort',) unique_together = ('sort', 'course') def upload_image(instance, _filename): return 'courses/%s/image.png' % instance.slug def upload_big_image(instance, _filename): return 'courses/%s/big_image.png' % instance.slug def upload_mobile_image(instance, _filename): return 'courses/%s/mobile_image.png' % instance.slug def default_slug(): return slugify(unidecode.unidecode('Python-разработчик с нуля (2018)')) class Course(models.Model): PRODUCERS = Choices('skillbox', 'Ingate', 'AIC') token = models.UUIDField(verbose_name="Токен", default=uuid.uuid4, editable=False) slug = models.SlugField(unique=True, editable=False, max_length=127, default=default_slug) title = models.CharField(verbose_name="Заголовок", max_length=255, unique=True) description = models.TextField(verbose_name='Описание', blank=True) level = models.CharField(verbose_name='Уровень', choices=COURSE_LEVEL, default='B', max_length=3) direction = models.SmallIntegerField(choices=COURSE_DIRECTION, verbose_name='Направление', default=1) public = models.BooleanField(verbose_name='Опубликовать', default=False) teacher_tokens = ArrayField( models.UUIDField(verbose_name="Токен препода", editable=False), default=get_empty_list, verbose_name='Преподователи курса', ) image = models.ImageField(verbose_name='Изображение', blank=True, max_length=255, upload_to=upload_image) big_image = models.ImageField( verbose_name='Большое изображение', blank=True, max_length=255, upload_to=upload_big_image) big_mobile_image = models.ImageField(verbose_name='Под мобилку', blank=True, upload_to=upload_mobile_image, help_text='Большая картинка для мобильной версии', max_length=255) hidden = models.BooleanField(verbose_name='Видно только оплатившим', default=False) producer = models.CharField( choices=PRODUCERS, default=PRODUCERS.skillbox, max_length=15, verbose_name="Производитель") def __str__(self): return self.title def get_teacher(self): return self.teacher_tokens[0] def get_statistic(self): return { 'topic_count': self.topic_set.all().count(), 'task_count': sum([topic.lesson_set.count() for topic in self.topic_set.all()]) } def get_lesson_list(self) -> list: lesson_list = [] for topic in self.topic_set.all(): lesson_list += list(topic.lesson_set.all()) return lesson_list def get_next(self, lesson: Lesson, f=None) -> Lesson: lessons = self.get_lesson_list() try: n = lessons[lessons.index(lesson)+1] if f is None or f(n): return n else: return self.get_next(n, f) except IndexError: pass def get_previous(self, lesson: Lesson, f=None): lessons = self.get_lesson_list() idx = lessons.index(lesson) - 1 if idx > -1: prev = lessons[idx] if f is None or f(prev): return prev else: return self.get_previous(prev, f) def get_first_lesson(self) -> Lesson: lessons = self.get_lesson_list() try: return lessons[0] except IndexError: pass class Meta: verbose_name = "Курс" verbose_name_plural = "Курсы" # class LessonRequirement(models.Model): # lesson = models.ForeignKey(to=Lesson) # requirement = models.ForeignKey(to='courses.Requirement') # sort = models.SmallIntegerField(default=1) # # class Meta: # verbose_name = "Порядок требований" # verbose_name_plural = "Порядок требований" # ordering = ('sort', ) # unique_together = ('lesson', 'requirement', 'sort') # # # class Requirement(models.Model): # CHECK_TYPES = Choices('student', 'teacher', 'auto',) # # token = models.UUIDField(verbose_name="Токен", default=uuid.uuid4, primary_key=True, editable=False) # name = models.CharField(max_length=31, verbose_name="Название", unique=True) # checker = models.CharField( # choices=CHECK_TYPES, default=CHECK_TYPES.teacher, max_length=15, verbose_name="Проверяющий",) # min_balls = models.SmallIntegerField(default=50, verbose_name='Проходной бал') # # def __str__(self): # return self.name # # class Meta: # verbose_name = "Требования" # verbose_name_plural = "Требования" # # # class Question(models.Model): # FIELD_TYPES = Choices('text', 'char', 'boolean', 'file') # # requirement = models.ForeignKey(to=Requirement) # text = models.TextField(verbose_name="Вопрос") # type = models.CharField(choices=FIELD_TYPES, default=FIELD_TYPES.char, max_length=20) # multiple = models.BooleanField(default=False) # null = models.BooleanField(default=False) # balls = models.SmallIntegerField(default=100, verbose_name='Вознаграждение') # # class Meta: # verbose_name = "Вопрос" # verbose_name_plural = "Вопросы" # # # class RightAnswer(models.Model): # question = models.OneToOneField(to=Question) # text = models.TextField(verbose_name="Верный ответ") # success_comment = models.TextField(blank=True, null=True, verbose_name="Комментарий при верном ответе") # error_comment = models.TextField(blank=True, null=True, verbose_name="Комментарий при ошибке") # # class Meta: # verbose_name = "Верный ответ" # verbose_name_plural = "Верные ответы"