From 9165bff91a69503f2daabb9e28ce66f9723fe750 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Fri, 16 Feb 2018 09:52:27 +0300 Subject: [PATCH 01/17] Add .editorconfig file --- .editorconfig | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .editorconfig diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 00000000..883f1f80 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,21 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[*.{py,rst,ini,ino}] +indent_style = space +indent_size = 4 + +[*.{html,css,scss,js,json,yml,vue}] +indent_style = space +indent_size = 2 + +[*.md] +trim_trailing_whitespace = false + +[Makefile] +indent_style = tab From b68bdffe75fb570e8cefdb23adad26b3a67be06a Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 19 Feb 2018 11:54:31 +0300 Subject: [PATCH 02/17] Update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 38adbfe2..a250ef4d 100644 --- a/.gitignore +++ b/.gitignore @@ -86,7 +86,7 @@ celerybeat-schedule .env .venv env/ -venv/ +venv*/ ENV/ env.bak/ venv.bak/ From bc1438721ccf428200a7dbf70f0cb72fd8ffef60 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Mon, 19 Feb 2018 20:58:48 +0300 Subject: [PATCH 03/17] LIL-276. Add courses category bulk change endpoint. --- api/v1/serializers/course.py | 8 ++++++++ api/v1/views.py | 27 +++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/api/v1/serializers/course.py b/api/v1/serializers/course.py index bacd4b30..b2cfdb81 100644 --- a/api/v1/serializers/course.py +++ b/api/v1/serializers/course.py @@ -72,6 +72,14 @@ class CategorySerializer(serializers.ModelSerializer): ) +class CourseBulkChangeCategorySerializer(serializers.Serializer): + category = serializers.IntegerField() + courses = serializers.ListField( + child=serializers.IntegerField(), + min_length=1, + ) + + class CourseCreateSerializer(DispatchContentMixin, DispatchGalleryMixin, DispatchMaterialMixin, diff --git a/api/v1/views.py b/api/v1/views.py index 16a0fc6f..635012a2 100644 --- a/api/v1/views.py +++ b/api/v1/views.py @@ -10,6 +10,7 @@ from . import ExtendedModelViewSet from .serializers.course import ( CategorySerializer, LikeSerializer, CourseSerializer, CourseCreateSerializer, + CourseBulkChangeCategorySerializer, MaterialSerializer, MaterialCreateSerializer, LessonSerializer, LessonCreateSerializer, ) @@ -82,6 +83,7 @@ class CourseViewSet(ExtendedModelViewSet): 'list': CourseSerializer, 'retrieve': CourseSerializer, 'draft': CourseSerializer, + 'change_category_bulk': CourseBulkChangeCategorySerializer, } filter_fields = ('category', 'status', 'is_infinite', 'is_featured',) search_fields = ('author__email', 'title', 'category__title',) @@ -99,6 +101,31 @@ class CourseViewSet(ExtendedModelViewSet): serialized_data = serializer(instance=drafts.last()) return Response(serialized_data.data) + @list_route(methods=['patch'], url_path='change-category-bulk') + def change_category_bulk(self, request): + serializer_class = self.get_serializer_class() + serializer = serializer_class(data=request.data) + if serializer.is_valid(): + category_id = serializer.validated_data['category'] + courses_ids = serializer.validated_data['courses'] + try: + category = Category.objects.get(id=category_id) + except Category.DoesNotExist: + return Response( + {'success': False, 'detail': f'Category with id {category_id} not found'}, + status=status.HTTP_400_BAD_REQUEST, + ) + else: + c = Course.objects.filter( + id__in=courses_ids, + ).update(category=category) + return Response({'success': True}) + else: + return Response( + {'success': False}, + status=status.HTTP_400_BAD_REQUEST, + ) + class LessonViewSet(ExtendedModelViewSet): queryset = Lesson.objects.select_related( From 1f39fc98117be4ad702322edb206f793b934a421 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Tue, 20 Feb 2018 11:46:34 +0300 Subject: [PATCH 04/17] LIL-276. Fix courses category bulk change endpoint. --- api/v1/serializers/course.py | 7 ++----- api/v1/views.py | 27 ++++++++++++++++++--------- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/api/v1/serializers/course.py b/api/v1/serializers/course.py index b2cfdb81..8139d8fa 100644 --- a/api/v1/serializers/course.py +++ b/api/v1/serializers/course.py @@ -73,11 +73,8 @@ class CategorySerializer(serializers.ModelSerializer): class CourseBulkChangeCategorySerializer(serializers.Serializer): - category = serializers.IntegerField() - courses = serializers.ListField( - child=serializers.IntegerField(), - min_length=1, - ) + old_category = serializers.IntegerField() + new_category = serializers.IntegerField() class CourseCreateSerializer(DispatchContentMixin, diff --git a/api/v1/views.py b/api/v1/views.py index 635012a2..56c65ff9 100644 --- a/api/v1/views.py +++ b/api/v1/views.py @@ -106,20 +106,29 @@ class CourseViewSet(ExtendedModelViewSet): serializer_class = self.get_serializer_class() serializer = serializer_class(data=request.data) if serializer.is_valid(): - category_id = serializer.validated_data['category'] - courses_ids = serializer.validated_data['courses'] + old_category_id = serializer.validated_data['old_category'] + new_category_id = serializer.validated_data['new_category'] try: - category = Category.objects.get(id=category_id) + old_category = Category.objects.get(id=old_category_id) except Category.DoesNotExist: return Response( - {'success': False, 'detail': f'Category with id {category_id} not found'}, + {'success': False, 'detail': f'Category with id {old_category_id} not found'}, status=status.HTTP_400_BAD_REQUEST, ) - else: - c = Course.objects.filter( - id__in=courses_ids, - ).update(category=category) - return Response({'success': True}) + try: + new_category = Category.objects.get(id=new_category_id) + except Category.DoesNotExist: + return Response( + {'success': False, 'detail': f'Category with id {new_category_id} not found'}, + status=status.HTTP_400_BAD_REQUEST, + ) + + c = Course.objects.filter( + category=old_category, + ).update( + category=new_category + ) + return Response({'success': True}) else: return Response( {'success': False}, From 09fe0298a864a002b927d2dd6e628cb646b1d34d Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Tue, 20 Feb 2018 12:03:30 +0300 Subject: [PATCH 05/17] LIL-16. Add django-constance[database] to req --- requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/requirements.txt b/requirements.txt index fa1be26b..5e9e81b0 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,3 +16,4 @@ djangorestframework==3.7.7 drf-yasg[validation]==1.4.0 django-silk==2.0.0 django-cors-headers==2.1.0 +django-constance[database]==2.1.0 \ No newline at end of file From 76da0b4371b43fb994a44cc337d365ad881b5505 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Tue, 20 Feb 2018 15:36:17 +0300 Subject: [PATCH 06/17] LIL-266. Add celery worker service --- docker-compose.yml | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index a6d65c69..647430e4 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -34,4 +34,23 @@ services: - redis links: - db - - redis \ No newline at end of file + - redis + + workers: + build: . + restart: always + volumes: + - .:/lilcity + command: bash -c "celery worker -A project -B" + environment: + - DJANGO_SETTINGS_MODULE=project.settings + - DATABASE_SERVICE_HOST=db + - REDIS_SERVICE_HOST=redis + depends_on: + - db + - redis + - web + links: + - db + - redis + - web From 265dc1ca441c30b69efcce4762f5c9c5d2c4c184 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Tue, 20 Feb 2018 15:36:50 +0300 Subject: [PATCH 07/17] LIL-16. Add instagram api lib to req --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 5e9e81b0..e02b575a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -16,4 +16,5 @@ djangorestframework==3.7.7 drf-yasg[validation]==1.4.0 django-silk==2.0.0 django-cors-headers==2.1.0 -django-constance[database]==2.1.0 \ No newline at end of file +django-constance[database]==2.1.0 +InstagramAPI==1.0.2 From a2f00458b46e58ac4dd6f04de541f62d7b47eea3 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Tue, 20 Feb 2018 15:38:10 +0300 Subject: [PATCH 08/17] LIL-266. Fix celery app --- project/celery.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/celery.py b/project/celery.py index 8cbb640c..bbc97ed5 100644 --- a/project/celery.py +++ b/project/celery.py @@ -10,7 +10,7 @@ app = Celery('project') # the configuration object to child processes. # - namespace='CELERY' means all celery-related configuration keys # should have a `CELERY_` prefix. -app.config_from_object('project.celery_settings') +app.config_from_object('project.settings', namespace='CELERY') # Load task modules from all registered Django app configs. app.autodiscover_tasks() From 45f1dcfbf3f7cf00d70b6604be7c9a71eed98642 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Tue, 20 Feb 2018 15:39:32 +0300 Subject: [PATCH 09/17] LIL-266. Move celery settings to main settings file. --- project/celery_settings.py | 3 --- project/settings.py | 7 +++++++ 2 files changed, 7 insertions(+), 3 deletions(-) delete mode 100644 project/celery_settings.py diff --git a/project/celery_settings.py b/project/celery_settings.py deleted file mode 100644 index 8afa610e..00000000 --- a/project/celery_settings.py +++ /dev/null @@ -1,3 +0,0 @@ -broker_url = 'redis://redis:6379/0' -result_backend = 'redis://redis:6379/1' -task_serializer = 'json' diff --git a/project/settings.py b/project/settings.py index 10c5e93b..6ec6ff69 100644 --- a/project/settings.py +++ b/project/settings.py @@ -205,6 +205,13 @@ REST_FRAMEWORK = { 'PAGE_SIZE': 10, } +# Celery settings + +CELERY_BROKER_URL = 'redis://redis:6379/0' +CELERY_RESULT_BACKEND = 'redis://redis:6379/1' +CELERY_TASK_SERIALIZER = 'json' + + # CORS settings if DEBUG: From fc301cc8ace3aaabec017bf591cee797c7875949 Mon Sep 17 00:00:00 2001 From: Ivlev Denis Date: Tue, 20 Feb 2018 15:41:41 +0300 Subject: [PATCH 10/17] LIL-266. Add instagram settings --- project/settings.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/project/settings.py b/project/settings.py index 6ec6ff69..93195e33 100644 --- a/project/settings.py +++ b/project/settings.py @@ -11,6 +11,7 @@ https://docs.djangoproject.com/en/2.0/ref/settings/ """ import os +from collections import OrderedDict # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) @@ -47,6 +48,8 @@ INSTALLED_APPS = [ 'rest_framework.authtoken', 'drf_yasg', 'corsheaders', + 'constance', + 'constance.backends.database', ] + [ 'apps.auth.apps', 'apps.user', @@ -212,6 +215,22 @@ CELERY_RESULT_BACKEND = 'redis://redis:6379/1' CELERY_TASK_SERIALIZER = 'json' +# Dynamic settings + +CONSTANCE_BACKEND = 'constance.backends.database.DatabaseBackend' +CONSTANCE_CONFIG = OrderedDict(( + ('INSTAGRAM_CLIENT_LOGIN', ('', '')), + ('INSTAGRAM_CLIENT_PASSWORD', ('', '')), + ('INSTAGRAM_RESULTS_TAG', ('#lil_акварель', 'Тэг результатов работ.')), + ('INSTAGRAM_RESULTS_PATH', ('media/instagram/results/', 'Путь до результатов работ.')), +)) + +try: + from .local_settings import * +except ImportError: + pass + + # CORS settings if DEBUG: From 126167db8a8206a69e7f44f51dd321e1a7bc0190 Mon Sep 17 00:00:00 2001 From: Sanasol Date: Tue, 20 Feb 2018 20:25:55 +0700 Subject: [PATCH 11/17] [LIL-279] layout profile school page --- apps/course/templates/course/school.html | 34 +++++++++ apps/user/templates/user/profile.html | 8 +++ web/src/sass/_common.sass | 92 +++++++++++++++++++++++- 3 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 apps/course/templates/course/school.html diff --git a/apps/course/templates/course/school.html b/apps/course/templates/course/school.html new file mode 100644 index 00000000..e0eaecf7 --- /dev/null +++ b/apps/course/templates/course/school.html @@ -0,0 +1,34 @@ +
+
+
+
+
Январь
+
Осталось 14 дней
+
+ +
+
+
+ + +
+
+ {% for course in course_items %} +
+
Понедельник
+
Пластилиновая живопись.
+
+

Научимся смешивать цвета, получать красивые оттенки и создавать картины из пластилина разными техниками. Узнаем как хранить и ухаживать за такими работами.

+
+
+ {% endfor %} +
+
\ No newline at end of file diff --git a/apps/user/templates/user/profile.html b/apps/user/templates/user/profile.html index 9af22213..aeec9433 100644 --- a/apps/user/templates/user/profile.html +++ b/apps/user/templates/user/profile.html @@ -71,6 +71,7 @@ + {% comment %}