From 042f823597e7feae5f01836bb35c367469bd3214 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 29 Jan 2018 16:03:22 +0300 Subject: [PATCH 01/13] Fix fb auth errors --- apps/auth/views.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/auth/views.py b/apps/auth/views.py index b932e5a9..4cea8327 100644 --- a/apps/auth/views.py +++ b/apps/auth/views.py @@ -133,10 +133,11 @@ class FacebookLoginOrRegistration(View): return JsonResponse({"success": False}) fb_id = data.get('id') + print(fb_id) lilcity_user_settings = User.objects.filter(fb_id=fb_id) if lilcity_user_settings.count(): - login(requests, user=lilcity_user_settings[0].user) + login(requests, user=lilcity_user_settings[0]) return JsonResponse({"success": True}) email = requests.POST.get('email') or data.get('email') From 8c6eea5a9c1da491a5ef9e54532e2d12f88dfecb Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 29 Jan 2018 17:37:38 +0300 Subject: [PATCH 02/13] =?UTF-8?q?LIL-102.=20=D0=A1=D0=BE=D0=B7=D0=B4=D0=B0?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=20=D0=BC=D0=BE=D0=B4=D0=B5=D0=BB=D0=B8=20?= =?UTF-8?q?=D1=83=D1=80=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/course/admin.py | 10 ++++++- apps/course/migrations/0006_lesson.py | 29 +++++++++++++++++++ .../migrations/0007_auto_20180129_1433.py | 17 +++++++++++ .../migrations/0008_auto_20180129_1436.py | 25 ++++++++++++++++ apps/course/models.py | 21 ++++++++++++++ 5 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 apps/course/migrations/0006_lesson.py create mode 100644 apps/course/migrations/0007_auto_20180129_1433.py create mode 100644 apps/course/migrations/0008_auto_20180129_1436.py diff --git a/apps/course/admin.py b/apps/course/admin.py index 9b5cd1ae..762ac27e 100644 --- a/apps/course/admin.py +++ b/apps/course/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from .models import Course, Category +from .models import Course, Category, Lesson @admin.register(Course) @@ -20,3 +20,11 @@ class CourseAdmin(admin.ModelAdmin): @admin.register(Category) class CategoryAdmin(admin.ModelAdmin): pass + + +@admin.register(Lesson) +class LessonAdmin(admin.ModelAdmin): + list_display = ( + 'title', + 'course', + ) diff --git a/apps/course/migrations/0006_lesson.py b/apps/course/migrations/0006_lesson.py new file mode 100644 index 00000000..0d095d28 --- /dev/null +++ b/apps/course/migrations/0006_lesson.py @@ -0,0 +1,29 @@ +# Generated by Django 2.0.1 on 2018-01-29 14:07 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('course', '0005_course_from_author'), + ] + + operations = [ + migrations.CreateModel( + name='Lesson', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=100, verbose_name='Название урока')), + ('short_description', models.TextField(verbose_name='Краткое описание курса')), + ('cover', models.ImageField(upload_to='lessons', verbose_name='Фон урока')), + ('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='lessons', to='course.Course')), + ], + options={ + 'verbose_name': 'Урок', + 'verbose_name_plural': 'Уроки', + 'ordering': ('-title',), + }, + ), + ] diff --git a/apps/course/migrations/0007_auto_20180129_1433.py b/apps/course/migrations/0007_auto_20180129_1433.py new file mode 100644 index 00000000..6f2bc7b7 --- /dev/null +++ b/apps/course/migrations/0007_auto_20180129_1433.py @@ -0,0 +1,17 @@ +# Generated by Django 2.0.1 on 2018-01-29 14:33 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('course', '0006_lesson'), + ] + + operations = [ + migrations.AlterModelOptions( + name='lesson', + options={'ordering': ('title',), 'verbose_name': 'Урок', 'verbose_name_plural': 'Уроки'}, + ), + ] diff --git a/apps/course/migrations/0008_auto_20180129_1436.py b/apps/course/migrations/0008_auto_20180129_1436.py new file mode 100644 index 00000000..189d08b1 --- /dev/null +++ b/apps/course/migrations/0008_auto_20180129_1436.py @@ -0,0 +1,25 @@ +# Generated by Django 2.0.1 on 2018-01-29 14:36 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('course', '0007_auto_20180129_1433'), + ] + + operations = [ + migrations.AddField( + model_name='lesson', + name='created_at', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name='lesson', + name='update_at', + field=models.DateTimeField(auto_now=True), + ), + ] diff --git a/apps/course/models.py b/apps/course/models.py index 7c7ba259..3b5af116 100644 --- a/apps/course/models.py +++ b/apps/course/models.py @@ -62,6 +62,9 @@ class Course(models.Model): return True return False + def __str__(self): + return self.title + class Meta: verbose_name = "Курс" verbose_name_plural = "Курсы" @@ -77,3 +80,21 @@ class Category(models.Model): class Meta: verbose_name = "Категория" verbose_name_plural = "Категории" + + +class Lesson(models.Model): + title = models.CharField("Название урока", max_length=100) + short_description = models.TextField("Краткое описание курса") + course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='lessons') + cover = models.ImageField("Фон урока", upload_to='lessons') + + created_at = models.DateTimeField(auto_now_add=True) + update_at = models.DateTimeField(auto_now=True) + + def __str__(self): + return self.title + + class Meta: + verbose_name = "Урок" + verbose_name_plural = "Уроки" + ordering = ('title',) From f79f4730f55d35bd94c61d555f0e75357f6ea091 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 29 Jan 2018 17:39:19 +0300 Subject: [PATCH 03/13] LIL-118. Show lessons in course detail view --- apps/course/templates/course/course.html | 51 +++++------------------- 1 file changed, 9 insertions(+), 42 deletions(-) diff --git a/apps/course/templates/course/course.html b/apps/course/templates/course/course.html index c6202d1d..7a461571 100644 --- a/apps/course/templates/course/course.html +++ b/apps/course/templates/course/course.html @@ -91,52 +91,19 @@
Содержание курса
+ {% for lesson in course.lessons.all %}
-
1 УРОК
+
{{ lesson.title }}
+ {% if lesson.cover %} +
+ {% else %}
-
Выбираем сюжет, с которым мы будем работать на курсе и главного героя вашей истории. С этим героем мы будем работать на протяжении всего курса.
+ {% endif %} +
{{ lesson.short_description | safe }}
-
-
-
2 УРОК
-
-
-
-

Выделяем основные черты внешности и характера вашего персонажа. Вам нужно будет ответить на несколько ключевых вопросов:


-

– Кто он и как он выглядит?

-

– Где и в какое время он живет?

-

– Какой его характерный признак?

-
-
-
-
-
1 УРОК
-
-
-
-

Собираем материал и экспериментируем с образом героя, используя полученный список характерных особенностей персонажа. По каждому признаку нужно будет собрать «референсы». Рисуем элементы образа в своем стиле.

-

Собираем из них нашего персонажа. Выбираем самые удачные элементы, объединяем их в одном наброске.

-
-
-
-
-
1 УРОК
-
-
-
-

Попробуем оживить персонажа. Выбираем 5 характерных действий для вашего героя и того сюжета, в котором он принимает участие, рисуем эскизы вашего персонажа в разных характерных для него позах и движении.

-

Выделяем 5 характерных эмоций для героя, над которым работаем. По эмоциям подбираем референсы и стилизуем их в своем стиле.

-
-
-
-
-
1 УРОК
-
-
-
Адаптируем вашего героя в соответствии с целевой аудиторией. Рассматриваем, как люди разных возрастов по разному воспринимают образы, героев и их эмоции. Выделяем 3 основные группы — дети, подростки и взрослые люди.
-
-
+
+ {% endfor %}
From 4921c3fb0ac0747f991cb97d2183849319cf110a Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 29 Jan 2018 17:41:22 +0300 Subject: [PATCH 04/13] Replace " to ' --- apps/course/models.py | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/apps/course/models.py b/apps/course/models.py index 3b5af116..2a9f881d 100644 --- a/apps/course/models.py +++ b/apps/course/models.py @@ -22,15 +22,15 @@ class Course(models.Model): (2, 'Archived'), ) author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True) - title = models.CharField("Название курса", max_length=100) - short_description = models.TextField("Краткое описание курса") - from_author = models.TextField("От автора", default='') - cover = models.ImageField("Фон курса", upload_to='courses') - price = models.DecimalField("Цена курса", help_text="Если цены нету, то курс бесплатный", max_digits=10, decimal_places=2, null=True, blank=True) + title = models.CharField('Название курса', max_length=100) + short_description = models.TextField('Краткое описание курса') + from_author = models.TextField('От автора', default='') + cover = models.ImageField('Фон курса', upload_to='courses') + price = models.DecimalField('Цена курса', help_text='Если цены нету, то курс бесплатный', max_digits=10, decimal_places=2, null=True, blank=True) is_infinite = models.BooleanField(default=False) - deferred_start_at = models.DateTimeField("Отложенный запуск курса", help_text="Заполнить если курс отложенный", null=True, blank=True) - category = models.ForeignKey("Category", on_delete=models.PROTECT) - duration = models.IntegerField("Продолжительность курса", default=0) + deferred_start_at = models.DateTimeField('Отложенный запуск курса', help_text='Заполнить если курс отложенный', null=True, blank=True) + category = models.ForeignKey('Category', on_delete=models.PROTECT) + duration = models.IntegerField('Продолжительность курса', default=0) is_featured = models.BooleanField(default=False) url = models.URLField('Ссылка', default='') status = models.PositiveSmallIntegerField('Статус', default=0, choices=STATUS_CHOICES) @@ -66,27 +66,27 @@ class Course(models.Model): return self.title class Meta: - verbose_name = "Курс" - verbose_name_plural = "Курсы" + verbose_name = 'Курс' + verbose_name_plural = 'Курсы' ordering = ['-created_at'] class Category(models.Model): - title = models.CharField("Название категории", max_length=100) + title = models.CharField('Название категории', max_length=100) def __str__(self): return self.title class Meta: - verbose_name = "Категория" - verbose_name_plural = "Категории" + verbose_name = 'Категория' + verbose_name_plural = 'Категории' class Lesson(models.Model): - title = models.CharField("Название урока", max_length=100) - short_description = models.TextField("Краткое описание курса") + title = models.CharField('Название урока', max_length=100) + short_description = models.TextField('Краткое описание курса') course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='lessons') - cover = models.ImageField("Фон урока", upload_to='lessons') + cover = models.ImageField('Фон урока', upload_to='lessons') created_at = models.DateTimeField(auto_now_add=True) update_at = models.DateTimeField(auto_now=True) @@ -95,6 +95,6 @@ class Lesson(models.Model): return self.title class Meta: - verbose_name = "Урок" - verbose_name_plural = "Уроки" + verbose_name = 'Урок' + verbose_name_plural = 'Уроки' ordering = ('title',) From e045e50e57eb4bca5ea9c61cffef78b47b867e32 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 29 Jan 2018 18:01:07 +0300 Subject: [PATCH 05/13] LIL-126 Add Material model --- apps/course/admin.py | 9 ++++- .../migrations/0009_auto_20180129_1458.py | 39 +++++++++++++++++++ apps/course/models.py | 20 +++++++++- 3 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 apps/course/migrations/0009_auto_20180129_1458.py diff --git a/apps/course/admin.py b/apps/course/admin.py index 762ac27e..683f950f 100644 --- a/apps/course/admin.py +++ b/apps/course/admin.py @@ -1,6 +1,6 @@ from django.contrib import admin -from .models import Course, Category, Lesson +from .models import Course, Category, Lesson, Material @admin.register(Course) @@ -28,3 +28,10 @@ class LessonAdmin(admin.ModelAdmin): 'title', 'course', ) + + +@admin.register(Material) +class MaterialAdmin(admin.ModelAdmin): + list_display = ( + 'title', + ) diff --git a/apps/course/migrations/0009_auto_20180129_1458.py b/apps/course/migrations/0009_auto_20180129_1458.py new file mode 100644 index 00000000..d3cdaf3e --- /dev/null +++ b/apps/course/migrations/0009_auto_20180129_1458.py @@ -0,0 +1,39 @@ +# Generated by Django 2.0.1 on 2018-01-29 14:58 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('course', '0008_auto_20180129_1436'), + ] + + operations = [ + migrations.CreateModel( + name='Material', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=100, verbose_name='Название материала')), + ('cover', models.ImageField(upload_to='lessons', verbose_name='Фон материала')), + ('short_description', models.TextField(verbose_name='Краткое описание материала')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('update_at', models.DateTimeField(auto_now=True)), + ], + options={ + 'verbose_name': 'Материал', + 'verbose_name_plural': 'Материалы', + 'ordering': ('title',), + }, + ), + migrations.AlterField( + model_name='lesson', + name='short_description', + field=models.TextField(verbose_name='Краткое описание урока'), + ), + migrations.AddField( + model_name='course', + name='materials', + field=models.ManyToManyField(to='course.Material'), + ), + ] diff --git a/apps/course/models.py b/apps/course/models.py index 2a9f881d..31f85487 100644 --- a/apps/course/models.py +++ b/apps/course/models.py @@ -35,6 +35,7 @@ class Course(models.Model): url = models.URLField('Ссылка', default='') status = models.PositiveSmallIntegerField('Статус', default=0, choices=STATUS_CHOICES) likes = models.ManyToManyField(Like) + materials = models.ManyToManyField('Material') created_at = models.DateTimeField(auto_now_add=True) update_at = models.DateTimeField(auto_now=True) @@ -84,7 +85,7 @@ class Category(models.Model): class Lesson(models.Model): title = models.CharField('Название урока', max_length=100) - short_description = models.TextField('Краткое описание курса') + short_description = models.TextField('Краткое описание урока') course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='lessons') cover = models.ImageField('Фон урока', upload_to='lessons') @@ -98,3 +99,20 @@ class Lesson(models.Model): verbose_name = 'Урок' verbose_name_plural = 'Уроки' ordering = ('title',) + + +class Material(models.Model): + title = models.CharField('Название материала', max_length=100) + cover = models.ImageField('Фон материала', upload_to='lessons') + short_description = models.TextField('Краткое описание материала') + + created_at = models.DateTimeField(auto_now_add=True) + update_at = models.DateTimeField(auto_now=True) + + def __str__(self): + return self.title + + class Meta: + verbose_name = 'Материал' + verbose_name_plural = 'Материалы' + ordering = ('title',) From 261d8d3ba2ffe879b2ff285e40a7a737291559c6 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 29 Jan 2018 18:01:58 +0300 Subject: [PATCH 06/13] Fix material cover save path --- .../migrations/0010_auto_20180129_1501.py | 18 ++++++++++++++++++ apps/course/models.py | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 apps/course/migrations/0010_auto_20180129_1501.py diff --git a/apps/course/migrations/0010_auto_20180129_1501.py b/apps/course/migrations/0010_auto_20180129_1501.py new file mode 100644 index 00000000..305afaaa --- /dev/null +++ b/apps/course/migrations/0010_auto_20180129_1501.py @@ -0,0 +1,18 @@ +# Generated by Django 2.0.1 on 2018-01-29 15:01 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('course', '0009_auto_20180129_1458'), + ] + + operations = [ + migrations.AlterField( + model_name='material', + name='cover', + field=models.ImageField(upload_to='materials', verbose_name='Фон материала'), + ), + ] diff --git a/apps/course/models.py b/apps/course/models.py index 31f85487..705d3eef 100644 --- a/apps/course/models.py +++ b/apps/course/models.py @@ -103,7 +103,7 @@ class Lesson(models.Model): class Material(models.Model): title = models.CharField('Название материала', max_length=100) - cover = models.ImageField('Фон материала', upload_to='lessons') + cover = models.ImageField('Фон материала', upload_to='materials') short_description = models.TextField('Краткое описание материала') created_at = models.DateTimeField(auto_now_add=True) From ee20e92e93bd6cf5aeed2006a48921ef38450436 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 29 Jan 2018 18:28:30 +0300 Subject: [PATCH 07/13] Fix course model --- .../migrations/0011_auto_20180129_1527.py | 28 +++++++++++++++++++ apps/course/models.py | 6 ++-- 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 apps/course/migrations/0011_auto_20180129_1527.py diff --git a/apps/course/migrations/0011_auto_20180129_1527.py b/apps/course/migrations/0011_auto_20180129_1527.py new file mode 100644 index 00000000..c2214936 --- /dev/null +++ b/apps/course/migrations/0011_auto_20180129_1527.py @@ -0,0 +1,28 @@ +# Generated by Django 2.0.1 on 2018-01-29 15:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('course', '0010_auto_20180129_1501'), + ] + + operations = [ + migrations.AlterField( + model_name='course', + name='from_author', + field=models.TextField(blank=True, default='', null=True, verbose_name='От автора'), + ), + migrations.AlterField( + model_name='course', + name='likes', + field=models.ManyToManyField(blank=True, to='course.Like'), + ), + migrations.AlterField( + model_name='course', + name='materials', + field=models.ManyToManyField(blank=True, to='course.Material'), + ), + ] diff --git a/apps/course/models.py b/apps/course/models.py index 705d3eef..f8cfab87 100644 --- a/apps/course/models.py +++ b/apps/course/models.py @@ -24,7 +24,7 @@ class Course(models.Model): author = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True) title = models.CharField('Название курса', max_length=100) short_description = models.TextField('Краткое описание курса') - from_author = models.TextField('От автора', default='') + from_author = models.TextField('От автора', default='', null=True, blank=True) cover = models.ImageField('Фон курса', upload_to='courses') price = models.DecimalField('Цена курса', help_text='Если цены нету, то курс бесплатный', max_digits=10, decimal_places=2, null=True, blank=True) is_infinite = models.BooleanField(default=False) @@ -34,8 +34,8 @@ class Course(models.Model): is_featured = models.BooleanField(default=False) url = models.URLField('Ссылка', default='') status = models.PositiveSmallIntegerField('Статус', default=0, choices=STATUS_CHOICES) - likes = models.ManyToManyField(Like) - materials = models.ManyToManyField('Material') + likes = models.ManyToManyField(Like, blank=True) + materials = models.ManyToManyField('Material', blank=True) created_at = models.DateTimeField(auto_now_add=True) update_at = models.DateTimeField(auto_now=True) From c1c61f6e222df0e74bd00ffaf28e7e0c65357a38 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 29 Jan 2018 18:29:03 +0300 Subject: [PATCH 08/13] Add material list to course template --- apps/course/templates/course/course.html | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/apps/course/templates/course/course.html b/apps/course/templates/course/course.html index 7a461571..70ca5264 100644 --- a/apps/course/templates/course/course.html +++ b/apps/course/templates/course/course.html @@ -113,20 +113,19 @@
Материалы, которые понадобятся
+ {% for material in course.materials.all %}
+ {% if material.cover %} +
+ {% else %}
+ {% endif %}
-
Бумага акварельная
-
Этот курс поможет детям узнать о том как из простых форм создавать веселый и харизматичных персонажей.
-
-
-
-
-
-
Бумага акварельная
-
Этот курс поможет детям узнать о том как из простых форм создавать веселый и харизматичных персонажей.
+
{{ material.title }}
+
{{ material.short_description }}
+ {% endfor %}
From 186d1587c0743b4bc76d20a117147a255b26bc87 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 29 Jan 2018 19:08:28 +0300 Subject: [PATCH 09/13] Fix course template --- apps/course/templates/course/course.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/course/templates/course/course.html b/apps/course/templates/course/course.html index 70ca5264..38872a00 100644 --- a/apps/course/templates/course/course.html +++ b/apps/course/templates/course/course.html @@ -36,7 +36,7 @@
-
12 часов
+
{{ course.duration }}
@@ -50,7 +50,7 @@
-
5 уроков
+
{{ course.lessons.count }}
@@ -176,7 +176,7 @@
-
12 часов
+
{{ course.duration }}
From 50a3862594ab76bb4f0ec00308d5f2e4fe367a55 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 29 Jan 2018 19:52:19 +0300 Subject: [PATCH 10/13] LIL-119. Add django-mptt to req --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index 17ee0f7c..f059ea19 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,3 +9,4 @@ Pillow==5.0.0 django-active-link==0.1.2 arrow==0.12.1 django-filter==2.0.0.dev1 +django-mptt==0.9.0 From 9919591ced9ed52732a3968d8e6e3a4164902db7 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 29 Jan 2018 20:17:15 +0300 Subject: [PATCH 11/13] LIL-119. Add mptt app to settings --- project/settings.py | 1 + 1 file changed, 1 insertion(+) diff --git a/project/settings.py b/project/settings.py index 8e3c8a81..41d842cc 100644 --- a/project/settings.py +++ b/project/settings.py @@ -40,6 +40,7 @@ INSTALLED_APPS = [ 'anymail', 'active_link', 'django_filters', + 'mptt', ] + [ 'apps.auth.apps', 'apps.user', From caaaa90fb4600d6c3a8ee6f721463b084e9ce7eb Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 29 Jan 2018 21:27:25 +0300 Subject: [PATCH 12/13] LIL-119 Create comments model --- apps/course/admin.py | 13 +- apps/course/migrations/0012_comment.py | 35 +++++ .../migrations/0013_auto_20180129_1715.py | 17 +++ .../migrations/0014_auto_20180129_1726.py | 70 +++++++++ .../migrations/0015_auto_20180129_1733.py | 135 ++++++++++++++++++ .../migrations/0016_auto_20180129_1756.py | 24 ++++ apps/course/models.py | 40 +++++- 7 files changed, 332 insertions(+), 2 deletions(-) create mode 100644 apps/course/migrations/0012_comment.py create mode 100644 apps/course/migrations/0013_auto_20180129_1715.py create mode 100644 apps/course/migrations/0014_auto_20180129_1726.py create mode 100644 apps/course/migrations/0015_auto_20180129_1733.py create mode 100644 apps/course/migrations/0016_auto_20180129_1756.py diff --git a/apps/course/admin.py b/apps/course/admin.py index 683f950f..dab42062 100644 --- a/apps/course/admin.py +++ b/apps/course/admin.py @@ -1,6 +1,7 @@ from django.contrib import admin +from mptt.admin import MPTTModelAdmin, DraggableMPTTAdmin -from .models import Course, Category, Lesson, Material +from .models import Course, Category, Lesson, Material, CourseComment, LessonComment @admin.register(Course) @@ -35,3 +36,13 @@ class MaterialAdmin(admin.ModelAdmin): list_display = ( 'title', ) + + +@admin.register(CourseComment) +class CourseCommentAdmin(DraggableMPTTAdmin): + pass + + +@admin.register(LessonComment) +class LessonCommentAdmin(DraggableMPTTAdmin): + pass diff --git a/apps/course/migrations/0012_comment.py b/apps/course/migrations/0012_comment.py new file mode 100644 index 00000000..fe3f6e14 --- /dev/null +++ b/apps/course/migrations/0012_comment.py @@ -0,0 +1,35 @@ +# Generated by Django 2.0.1 on 2018-01-29 17:09 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import mptt.fields + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('course', '0011_auto_20180129_1527'), + ] + + operations = [ + migrations.CreateModel( + name='Comment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content', models.TextField(default='', verbose_name='Текст комментария')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('update_at', models.DateTimeField(auto_now=True)), + ('lft', models.PositiveIntegerField(db_index=True, editable=False)), + ('rght', models.PositiveIntegerField(db_index=True, editable=False)), + ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), + ('level', models.PositiveIntegerField(db_index=True, editable=False)), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='children', to='course.Comment')), + ], + options={ + 'abstract': False, + }, + ), + ] diff --git a/apps/course/migrations/0013_auto_20180129_1715.py b/apps/course/migrations/0013_auto_20180129_1715.py new file mode 100644 index 00000000..47be2f6f --- /dev/null +++ b/apps/course/migrations/0013_auto_20180129_1715.py @@ -0,0 +1,17 @@ +# Generated by Django 2.0.1 on 2018-01-29 17:15 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('course', '0012_comment'), + ] + + operations = [ + migrations.AlterModelOptions( + name='comment', + options={'verbose_name': 'Комментарий', 'verbose_name_plural': 'Комментарии'}, + ), + ] diff --git a/apps/course/migrations/0014_auto_20180129_1726.py b/apps/course/migrations/0014_auto_20180129_1726.py new file mode 100644 index 00000000..8330ba86 --- /dev/null +++ b/apps/course/migrations/0014_auto_20180129_1726.py @@ -0,0 +1,70 @@ +# Generated by Django 2.0.1 on 2018-01-29 17:26 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import mptt.fields + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('course', '0013_auto_20180129_1715'), + ] + + operations = [ + migrations.CreateModel( + name='CourseComment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content', models.TextField(default='', verbose_name='Текст комментария')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('update_at', models.DateTimeField(auto_now=True)), + ('lft', models.PositiveIntegerField(db_index=True, editable=False)), + ('rght', models.PositiveIntegerField(db_index=True, editable=False)), + ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), + ('level', models.PositiveIntegerField(db_index=True, editable=False)), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='course.Course')), + ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='children', to='course.CourseComment')), + ], + options={ + 'verbose_name': 'Комментарий', + 'verbose_name_plural': 'Комментарии', + 'abstract': False, + }, + ), + migrations.CreateModel( + name='LessonComment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content', models.TextField(default='', verbose_name='Текст комментария')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('update_at', models.DateTimeField(auto_now=True)), + ('lft', models.PositiveIntegerField(db_index=True, editable=False)), + ('rght', models.PositiveIntegerField(db_index=True, editable=False)), + ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), + ('level', models.PositiveIntegerField(db_index=True, editable=False)), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ('lesson', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='course.Lesson')), + ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='children', to='course.LessonComment')), + ], + options={ + 'verbose_name': 'Комментарий', + 'verbose_name_plural': 'Комментарии', + 'abstract': False, + }, + ), + migrations.RemoveField( + model_name='comment', + name='author', + ), + migrations.RemoveField( + model_name='comment', + name='parent', + ), + migrations.DeleteModel( + name='Comment', + ), + ] diff --git a/apps/course/migrations/0015_auto_20180129_1733.py b/apps/course/migrations/0015_auto_20180129_1733.py new file mode 100644 index 00000000..986fb1ed --- /dev/null +++ b/apps/course/migrations/0015_auto_20180129_1733.py @@ -0,0 +1,135 @@ +# Generated by Django 2.0.1 on 2018-01-29 17:33 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion +import mptt.fields + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('course', '0014_auto_20180129_1726'), + ] + + operations = [ + migrations.CreateModel( + name='Comment', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('content', models.TextField(default='', verbose_name='Текст комментария')), + ('created_at', models.DateTimeField(auto_now_add=True)), + ('update_at', models.DateTimeField(auto_now=True)), + ('lft', models.PositiveIntegerField(db_index=True, editable=False)), + ('rght', models.PositiveIntegerField(db_index=True, editable=False)), + ('tree_id', models.PositiveIntegerField(db_index=True, editable=False)), + ('level', models.PositiveIntegerField(db_index=True, editable=False)), + ('author', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to=settings.AUTH_USER_MODEL)), + ('parent', mptt.fields.TreeForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='children', to='course.Comment')), + ], + options={ + 'abstract': False, + }, + ), + migrations.AlterModelOptions( + name='coursecomment', + options={'verbose_name': 'Комментарий курса', 'verbose_name_plural': 'Комментарии курсов'}, + ), + migrations.AlterModelOptions( + name='lessoncomment', + options={'verbose_name': 'Комментарий урока', 'verbose_name_plural': 'Комментарии уроков'}, + ), + migrations.RemoveField( + model_name='coursecomment', + name='author', + ), + migrations.RemoveField( + model_name='coursecomment', + name='content', + ), + migrations.RemoveField( + model_name='coursecomment', + name='created_at', + ), + migrations.RemoveField( + model_name='coursecomment', + name='id', + ), + migrations.RemoveField( + model_name='coursecomment', + name='level', + ), + migrations.RemoveField( + model_name='coursecomment', + name='lft', + ), + migrations.RemoveField( + model_name='coursecomment', + name='parent', + ), + migrations.RemoveField( + model_name='coursecomment', + name='rght', + ), + migrations.RemoveField( + model_name='coursecomment', + name='tree_id', + ), + migrations.RemoveField( + model_name='coursecomment', + name='update_at', + ), + migrations.RemoveField( + model_name='lessoncomment', + name='author', + ), + migrations.RemoveField( + model_name='lessoncomment', + name='content', + ), + migrations.RemoveField( + model_name='lessoncomment', + name='created_at', + ), + migrations.RemoveField( + model_name='lessoncomment', + name='id', + ), + migrations.RemoveField( + model_name='lessoncomment', + name='level', + ), + migrations.RemoveField( + model_name='lessoncomment', + name='lft', + ), + migrations.RemoveField( + model_name='lessoncomment', + name='parent', + ), + migrations.RemoveField( + model_name='lessoncomment', + name='rght', + ), + migrations.RemoveField( + model_name='lessoncomment', + name='tree_id', + ), + migrations.RemoveField( + model_name='lessoncomment', + name='update_at', + ), + migrations.AddField( + model_name='coursecomment', + name='comment_ptr', + field=models.OneToOneField(auto_created=True, default=0, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='course.Comment'), + preserve_default=False, + ), + migrations.AddField( + model_name='lessoncomment', + name='comment_ptr', + field=models.OneToOneField(auto_created=True, default=0, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='course.Comment'), + preserve_default=False, + ), + ] diff --git a/apps/course/migrations/0016_auto_20180129_1756.py b/apps/course/migrations/0016_auto_20180129_1756.py new file mode 100644 index 00000000..56672ad6 --- /dev/null +++ b/apps/course/migrations/0016_auto_20180129_1756.py @@ -0,0 +1,24 @@ +# Generated by Django 2.0.1 on 2018-01-29 17:56 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('course', '0015_auto_20180129_1733'), + ] + + operations = [ + migrations.AlterField( + model_name='coursecomment', + name='course', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='course.Course'), + ), + migrations.AlterField( + model_name='lessoncomment', + name='lesson', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='comments', to='course.Lesson'), + ), + ] diff --git a/apps/course/models.py b/apps/course/models.py index f8cfab87..0b851950 100644 --- a/apps/course/models.py +++ b/apps/course/models.py @@ -3,6 +3,8 @@ from django.db import models from django.utils import timezone from django.contrib.auth import get_user_model +from mptt.models import MPTTModel, TreeForeignKey + from .manager import CategoryQuerySet User = get_user_model() @@ -64,7 +66,7 @@ class Course(models.Model): return False def __str__(self): - return self.title + return str(self.id) + ' ' + self.title class Meta: verbose_name = 'Курс' @@ -116,3 +118,39 @@ class Material(models.Model): verbose_name = 'Материал' verbose_name_plural = 'Материалы' ordering = ('title',) + + +class Comment(MPTTModel): + parent = TreeForeignKey('self', null=True, blank=True, related_name='children', db_index=True, on_delete=models.PROTECT) + author = models.ForeignKey(User, on_delete=models.PROTECT) + content = models.TextField('Текст комментария', default='') + + created_at = models.DateTimeField(auto_now_add=True) + update_at = models.DateTimeField(auto_now=True) + + @property + def created_at_humanize(self): + return arrow.get(self.created_at).humanize(locale='ru') + + def __str__(self): + return self.content + + class MPTTMeta: + order_insertion_by = ['created_at'] + abstract = True + + +class CourseComment(Comment): + course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='comments') + + class Meta: + verbose_name = 'Комментарий курса' + verbose_name_plural = 'Комментарии курсов' + + +class LessonComment(Comment): + lesson = models.ForeignKey(Lesson, on_delete=models.CASCADE, related_name='comments') + + class Meta: + verbose_name = 'Комментарий урока' + verbose_name_plural = 'Комментарии уроков' From e53a524c46c53f97898af7c6b3aa17f6cb2200e8 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 29 Jan 2018 21:28:06 +0300 Subject: [PATCH 13/13] Add comments to course template --- apps/course/templates/course/course.html | 34 +++++++++++++++++------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/apps/course/templates/course/course.html b/apps/course/templates/course/course.html index 38872a00..fc847874 100644 --- a/apps/course/templates/course/course.html +++ b/apps/course/templates/course/course.html @@ -1,5 +1,6 @@ {% extends "templates/lilcity/index.html" %} {% load static %} +{% load mptt_tags %} {% block content %}
@@ -191,6 +192,7 @@
+
Задавайте вопросы:
@@ -199,17 +201,29 @@
-
-
-
-
-
Богиня Недалекая16 Сен, 16:52
-
А можно ли заниматься если у меня нет интернета и компьютера. Можно ли запустить видео на моей микроволновке?
+ {% recursetree course.comments.all %} + +
+ {% if node.author.photo %} +
+ {% else %} +
+ {% endif %} +
+
+
{{ node.author.get_full_name }}{{ node.created_at_humanize }}
+
{{ node.content }}
+
+
-
-
-
+ + {% if not node.is_leaf_node %} + {{ children }} + {% endif %} + {% endrecursetree %} + +