# -*- coding: utf-8 -*- import uuid import unidecode from django.contrib.postgres.fields import ArrayField from django.core.exceptions import ObjectDoesNotExist from django.db import models from django.template.defaultfilters import slugify from model_utils import Choices from lms.tools import decode_base64, get_real_name COURSE_LEVEL = ( ('B', 'Базовый'), ('A', 'Продвинутый'), ('E', 'Экспертный'), ('B+A', 'Базовый + Продвинутый'), ) COURSE_DIRECTION = ( (3, 'Бизнес'), (2, 'Веб-дизайн'), (1, 'Разработка'), (4, 'Рисование'), (5, 'Музыка'), ) class CourseManager(models.Manager): def update_or_create_course(self, image=None, big_image=None, id=0, big_mobile_image=None, slug=None, level=None, direction=None, **kwargs): slug = slug if slug else slugify(unidecode.unidecode(kwargs['title'])) if image: kwargs['image'] = decode_base64(image, 'course/image%s.png' % slug) if big_image: kwargs['big_image'] = decode_base64(big_image, 'course/big_image%s.png' % slug) if big_mobile_image: kwargs['big_mobile_image'] = decode_base64(big_mobile_image, 'course/big_mobile_image%s.png' % slug) if level: kwargs['level'] = get_real_name(COURSE_LEVEL, level) if direction: kwargs['direction'] = get_real_name(COURSE_DIRECTION, direction) try: course = self.get(id=id) for i in kwargs: if kwargs[i]: setattr(course, i, kwargs[i]) course.save() except ObjectDoesNotExist: kwargs['slug'] = slug course = self.create(**kwargs) return course class Course(models.Model): token = models.UUIDField(verbose_name="Токен", default=uuid.uuid4, primary_key=True, editable=False) slug = models.SlugField(unique=True, editable=False, max_length=127) 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='Направление') public = models.BooleanField(verbose_name='Опубликовать', default=False) teacher_tokens = ArrayField( models.UUIDField(verbose_name="Токен препода", primary_key=True, editable=False), default=[], verbose_name='Преподователи курса', ) image = models.URLField(verbose_name='Изображение', blank=True, max_length=255) big_image = models.URLField(verbose_name='Большое изображение', blank=True, max_length=255) big_mobile_image = models.URLField(verbose_name='Под мобилку', blank=True, help_text='Большая картинка для мобильной версии', max_length=255) hidden = models.BooleanField(verbose_name='Видно только оплатившим', default=False) def __str__(self): return self.title def get_statistic(self): return { 'topic_count': self.topic_set.all().count(), 'task_count': sum([topic.vertex_set.count() for topic in self.topic_set.all()]) } objects = CourseManager() class Meta: verbose_name = "Курс" verbose_name_plural = "Курсы" class Topic(models.Model): course = models.ForeignKey(to=Course, verbose_name='курс') title = models.CharField(verbose_name='Название', max_length=255) description = models.TextField(verbose_name='Описание', blank=True, null=True) icon = models.ImageField(verbose_name='Иконка темы', null=True, blank=True) class Meta: verbose_name = "Тема" verbose_name_plural = "Темы" class Lesson(models.Model): token = models.UUIDField(verbose_name="Токен", default=uuid.uuid4, primary_key=True, 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) material_tokens = ArrayField(models.CharField(max_length=15, blank=True, verbose_name='Материалы урока'), default=[]) free = models.BooleanField(default=False, verbose_name='Привилегии для узла не будут проверяться') sort = models.SmallIntegerField(unique=True) def __str__(self): return self.title class Meta: verbose_name = "Урок" verbose_name_plural = "Уроки" ordering = ('sort', ) class LessonDemand(models.Model): demand = models.ForeignKey(to='Demand') lesson = models.ForeignKey(to=Lesson) sort = models.SmallIntegerField(default=1) class Meta: verbose_name = "Порядок требований" verbose_name_plural = "Порядок требований" ordering = ('sort', ) unique_together = ('lesson', 'demand', 'sort') class Demand(models.Model): CHECK_TYPES = Choices('student', 'teacher', 'support',) 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 Field(models.Model): # TODO Нужно прикрутить предварительную валидацию FIELD_TYPES = Choices('text', 'char', 'boolean', 'file') demand = models.ForeignKey(to=Demand) label = models.CharField(max_length=255, 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) answers = ArrayField(models.CharField(max_length=255), blank=True, null=True) balls = models.SmallIntegerField(default=100, verbose_name='Вознаграждение') match = models.CharField( max_length=255, verbose_name='Если не нулевое значение, то при точном сопоставлении даёт положителбный ответ', blank=True, null=True) class Meta: verbose_name = "Поле" verbose_name_plural = "Поля"