diff --git a/.gitignore b/.gitignore index 944152f8..5f11bf53 100644 --- a/.gitignore +++ b/.gitignore @@ -110,4 +110,5 @@ venv.bak/ # JavaScript .map node_modules -db.sqlite3 \ No newline at end of file +db.sqlite3 +.vscode \ No newline at end of file diff --git a/apps/auth/views.py b/apps/auth/views.py index d1fcc322..b932e5a9 100644 --- a/apps/auth/views.py +++ b/apps/auth/views.py @@ -13,7 +13,6 @@ from django.views.generic import FormView, View from django.views.generic.edit import BaseFormView from apps.notification.utils import send_email -from apps.user.models import LilcityUserSettings, LilcityUserProxy from .forms import LearnerRegistrationForm from .tokens import verification_email_token @@ -30,7 +29,19 @@ class LearnerRegistrationView(FormView): email = form.cleaned_data['email'] password = form.cleaned_data['password'] - user = User.objects.create_user(username=email, email=email, first_name=first_name, last_name=last_name, password=password) + user, created = User.objects.get_or_create( + username=email, email=email, + first_name=first_name, last_name=last_name + ) + + if not created: + return JsonResponse({ + "success": False, + 'errors': {'__all__': [{'message': 'Возможно вы уже зарегистрированы?'}]} + }, status=400) + + user.set_password(password) + user.save() login(self.request, user) # fixme: change email text @@ -64,7 +75,8 @@ class LoginView(FormView): class VerificationEmailView(View): def get(self, request, *args, **kwargs): - is_valid_token = verification_email_token.check_token(request.user, kwargs.get('token')) + is_valid_token = verification_email_token.check_token( + request.user, kwargs.get('token')) if is_valid_token: lilcity_user_settings = request.user.lilcity_user_settings @@ -120,9 +132,9 @@ class FacebookLoginOrRegistration(View): except FacepyError: return JsonResponse({"success": False}) - facebook_id = data.get('id') + fb_id = data.get('id') - lilcity_user_settings = LilcityUserSettings.objects.filter(facebook_id=facebook_id) + lilcity_user_settings = User.objects.filter(fb_id=fb_id) if lilcity_user_settings.count(): login(requests, user=lilcity_user_settings[0].user) return JsonResponse({"success": True}) @@ -136,9 +148,8 @@ class FacebookLoginOrRegistration(View): first_name = data.get('first_name', '') last_name = data.get('last_name', '') - user = LilcityUserProxy.objects.create_user(username=email, email=email, first_name=first_name, last_name=last_name, password=uuid4().hex) - - user.lilcity_user_settings.is_verification_email = True - user.lilcity_user_settings.facebook_id = facebook_id - user.lilcity_user_settings.save() + user = User.objects.create_user(username=email, email=email, first_name=first_name, last_name=last_name, password=uuid4().hex) + user.is_email_proved = True + user.fb_id = fb_id + user.save() return JsonResponse({"success": True}) diff --git a/apps/course/admin.py b/apps/course/admin.py index 1fc02ef1..9b5cd1ae 100644 --- a/apps/course/admin.py +++ b/apps/course/admin.py @@ -5,7 +5,16 @@ from .models import Course, Category @admin.register(Course) class CourseAdmin(admin.ModelAdmin): - pass + list_display = ( + 'author', + 'title', + 'price', + 'is_infinite', + 'category', + 'status', + 'created_at', + 'update_at', + ) @admin.register(Category) diff --git a/apps/course/filters.py b/apps/course/filters.py new file mode 100644 index 00000000..827079e6 --- /dev/null +++ b/apps/course/filters.py @@ -0,0 +1,11 @@ +import django_filters + +from .models import Course + + +class CourseFilter(django_filters.FilterSet): + category = django_filters.CharFilter(field_name='category__title', lookup_expr='iexact') + + class Meta: + model = Course + fields = ['category'] diff --git a/apps/course/fixtures/course.json b/apps/course/fixtures/course.json new file mode 100644 index 00000000..7daa5139 --- /dev/null +++ b/apps/course/fixtures/course.json @@ -0,0 +1,285 @@ +[ + { + "model": "course.course", + "pk": 1, + "fields": { + "author": 1, + "title": "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u0443\u0440\u0441 \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u0439 \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438", + "short_description": "\u042d\u0442\u043e\u0442 \u043a\u0443\u0440\u0441 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u0442\u044f\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0444\u043e\u0440\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u0435\u043b\u044b\u0439 \u0438 \u0445\u0430\u0440\u0438\u0437\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439.", + "cover": "courses/pic-1_sTaZawQ.jpg", + "price": "50.00", + "is_infinite": false, + "deferred_start_at": null, + "category": 2, + "duration": 1, + "is_featured": false, + "url": "https://gitlab.com/", + "status": 0, + "created_at": "2018-01-27T07:04:41.113Z", + "update_at": "2018-01-27T07:12:04.168Z" + } + }, + { + "model": "course.course", + "pk": 2, + "fields": { + "author": 1, + "title": "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u0443\u0440\u0441 \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u0439 \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438", + "short_description": "\u042d\u0442\u043e\u0442 \u043a\u0443\u0440\u0441 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u0442\u044f\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0444\u043e\u0440\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u0435\u043b\u044b\u0439 \u0438 \u0445\u0430\u0440\u0438\u0437\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439.", + "cover": "courses/pic-1_sTaZawQ.jpg", + "price": "50.00", + "is_infinite": false, + "deferred_start_at": null, + "category": 1, + "duration": 1, + "is_featured": false, + "url": "https://gitlab.com/", + "status": 0, + "created_at": "2018-01-27T07:09:03.437Z", + "update_at": "2018-01-27T07:11:55.373Z" + } + }, + { + "model": "course.course", + "pk": 3, + "fields": { + "author": 1, + "title": "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u0443\u0440\u0441 \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u0439 \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438", + "short_description": "\u042d\u0442\u043e\u0442 \u043a\u0443\u0440\u0441 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u0442\u044f\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0444\u043e\u0440\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u0435\u043b\u044b\u0439 \u0438 \u0445\u0430\u0440\u0438\u0437\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439.", + "cover": "courses/pic-1_sTaZawQ.jpg", + "price": "50.00", + "is_infinite": false, + "deferred_start_at": null, + "category": 9, + "duration": 1, + "is_featured": false, + "url": "https://gitlab.com/", + "status": 0, + "created_at": "2018-01-27T07:09:03.442Z", + "update_at": "2018-01-27T07:11:43.838Z" + } + }, + { + "model": "course.course", + "pk": 4, + "fields": { + "author": 1, + "title": "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u0443\u0440\u0441 \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u0439 \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438", + "short_description": "\u042d\u0442\u043e\u0442 \u043a\u0443\u0440\u0441 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u0442\u044f\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0444\u043e\u0440\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u0435\u043b\u044b\u0439 \u0438 \u0445\u0430\u0440\u0438\u0437\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439.", + "cover": "courses/pic-1_sTaZawQ.jpg", + "price": "50.00", + "is_infinite": false, + "deferred_start_at": null, + "category": 8, + "duration": 1, + "is_featured": false, + "url": "https://gitlab.com/", + "status": 0, + "created_at": "2018-01-27T07:09:03.445Z", + "update_at": "2018-01-27T07:11:35.342Z" + } + }, + { + "model": "course.course", + "pk": 5, + "fields": { + "author": 1, + "title": "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u0443\u0440\u0441 \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u0439 \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438", + "short_description": "\u042d\u0442\u043e\u0442 \u043a\u0443\u0440\u0441 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u0442\u044f\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0444\u043e\u0440\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u0435\u043b\u044b\u0439 \u0438 \u0445\u0430\u0440\u0438\u0437\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439.", + "cover": "courses/pic-1_sTaZawQ.jpg", + "price": "50.00", + "is_infinite": false, + "deferred_start_at": null, + "category": 7, + "duration": 1, + "is_featured": false, + "url": "https://gitlab.com/", + "status": 0, + "created_at": "2018-01-27T07:09:03.449Z", + "update_at": "2018-01-27T07:11:26.725Z" + } + }, + { + "model": "course.course", + "pk": 6, + "fields": { + "author": 1, + "title": "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u0443\u0440\u0441 \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u0439 \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438", + "short_description": "\u042d\u0442\u043e\u0442 \u043a\u0443\u0440\u0441 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u0442\u044f\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0444\u043e\u0440\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u0435\u043b\u044b\u0439 \u0438 \u0445\u0430\u0440\u0438\u0437\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439.", + "cover": "courses/pic-1_sTaZawQ.jpg", + "price": "50.00", + "is_infinite": false, + "deferred_start_at": null, + "category": 6, + "duration": 1, + "is_featured": false, + "url": "https://gitlab.com/", + "status": 0, + "created_at": "2018-01-27T07:09:03.452Z", + "update_at": "2018-01-27T07:11:15.061Z" + } + }, + { + "model": "course.course", + "pk": 7, + "fields": { + "author": 1, + "title": "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u0443\u0440\u0441 \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u0439 \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438", + "short_description": "\u042d\u0442\u043e\u0442 \u043a\u0443\u0440\u0441 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u0442\u044f\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0444\u043e\u0440\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u0435\u043b\u044b\u0439 \u0438 \u0445\u0430\u0440\u0438\u0437\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439.", + "cover": "courses/pic-1_sTaZawQ.jpg", + "price": "50.00", + "is_infinite": false, + "deferred_start_at": null, + "category": 5, + "duration": 1, + "is_featured": false, + "url": "https://gitlab.com/", + "status": 0, + "created_at": "2018-01-27T07:09:03.455Z", + "update_at": "2018-01-27T07:11:03.583Z" + } + }, + { + "model": "course.course", + "pk": 8, + "fields": { + "author": 1, + "title": "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u0443\u0440\u0441 \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u0439 \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438", + "short_description": "\u042d\u0442\u043e\u0442 \u043a\u0443\u0440\u0441 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u0442\u044f\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0444\u043e\u0440\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u0435\u043b\u044b\u0439 \u0438 \u0445\u0430\u0440\u0438\u0437\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439.", + "cover": "courses/pic-1_sTaZawQ.jpg", + "price": "50.00", + "is_infinite": false, + "deferred_start_at": null, + "category": 4, + "duration": 1, + "is_featured": false, + "url": "https://gitlab.com/", + "status": 0, + "created_at": "2018-01-27T07:09:03.458Z", + "update_at": "2018-01-27T07:10:52.322Z" + } + }, + { + "model": "course.course", + "pk": 9, + "fields": { + "author": 1, + "title": "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u0443\u0440\u0441 \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u0439 \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438", + "short_description": "\u042d\u0442\u043e\u0442 \u043a\u0443\u0440\u0441 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u0442\u044f\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0444\u043e\u0440\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u0435\u043b\u044b\u0439 \u0438 \u0445\u0430\u0440\u0438\u0437\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439.", + "cover": "courses/pic-1_sTaZawQ.jpg", + "price": "50.00", + "is_infinite": false, + "deferred_start_at": null, + "category": 3, + "duration": 1, + "is_featured": false, + "url": "https://gitlab.com/", + "status": 0, + "created_at": "2018-01-27T07:09:03.461Z", + "update_at": "2018-01-27T07:10:42.721Z" + } + }, + { + "model": "course.course", + "pk": 10, + "fields": { + "author": 1, + "title": "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u0443\u0440\u0441 \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u0439 \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438", + "short_description": "\u042d\u0442\u043e\u0442 \u043a\u0443\u0440\u0441 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u0442\u044f\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0444\u043e\u0440\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u0435\u043b\u044b\u0439 \u0438 \u0445\u0430\u0440\u0438\u0437\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439.", + "cover": "courses/pic-1_sTaZawQ.jpg", + "price": "50.00", + "is_infinite": false, + "deferred_start_at": null, + "category": 2, + "duration": 1, + "is_featured": false, + "url": "https://gitlab.com/", + "status": 0, + "created_at": "2018-01-27T07:09:03.464Z", + "update_at": "2018-01-27T07:10:33.374Z" + } + }, + { + "model": "course.course", + "pk": 11, + "fields": { + "author": 1, + "title": "\u0411\u0430\u0437\u043e\u0432\u044b\u0439 \u043a\u0443\u0440\u0441 \u0434\u043b\u044f \u0434\u0435\u0442\u0435\u0439 \u043f\u043e \u043e\u0441\u043d\u043e\u0432\u0430\u043c \u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u0438", + "short_description": "\u042d\u0442\u043e\u0442 \u043a\u0443\u0440\u0441 \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u0434\u0435\u0442\u044f\u043c \u0443\u0437\u043d\u0430\u0442\u044c \u043e \u0442\u043e\u043c \u043a\u0430\u043a \u0438\u0437 \u043f\u0440\u043e\u0441\u0442\u044b\u0445 \u0444\u043e\u0440\u043c \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u0435\u0441\u0435\u043b\u044b\u0439 \u0438 \u0445\u0430\u0440\u0438\u0437\u043c\u0430\u0442\u0438\u0447\u043d\u044b\u0445 \u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436\u0435\u0439.", + "cover": "courses/pic-1_sTaZawQ.jpg", + "price": "50.00", + "is_infinite": false, + "deferred_start_at": null, + "category": 1, + "duration": 1, + "is_featured": false, + "url": "https://gitlab.com/", + "status": 0, + "created_at": "2018-01-27T07:09:03.467Z", + "update_at": "2018-01-27T07:09:03.467Z" + } + }, + { + "model": "course.category", + "pk": 1, + "fields": { + "title": "\u043f\u0435\u0440\u0441\u043e\u043d\u0430\u0436" + } + }, + { + "model": "course.category", + "pk": 2, + "fields": { + "title": "\u0430\u043a\u0432\u0430\u0440\u0435\u043b\u044c" + } + }, + { + "model": "course.category", + "pk": 3, + "fields": { + "title": "\u0438\u043b\u043b\u044e\u0441\u0442\u0440\u0430\u0446\u0438\u044f" + } + }, + { + "model": "course.category", + "pk": 4, + "fields": { + "title": "\u0430\u043d\u0438\u043c\u0430\u0446\u0438\u044f" + } + }, + { + "model": "course.category", + "pk": 5, + "fields": { + "title": "\u043f\u0430\u0441\u0442\u0435\u043b\u044c" + } + }, + { + "model": "course.category", + "pk": 6, + "fields": { + "title": "\u043f\u043b\u0430\u0441\u0442\u0438\u043b\u0438\u043d" + } + }, + { + "model": "course.category", + "pk": 7, + "fields": { + "title": "\u043a\u0440\u0435\u0430\u0442\u0438\u0432\u043d\u043e\u0435 \u043c\u044b\u0448\u043b\u0435\u043d\u0438\u0435" + } + }, + { + "model": "course.category", + "pk": 8, + "fields": { + "title": "\u043c\u043e\u0442\u043e\u0440\u0438\u043a\u0430" + } + }, + { + "model": "course.category", + "pk": 9, + "fields": { + "title": "\u0436\u0438\u0432\u043e\u043f\u0438\u0441\u044c" + } + } +] \ No newline at end of file diff --git a/apps/course/migrations/0002_auto_20180126_1325.py b/apps/course/migrations/0002_auto_20180126_1325.py new file mode 100644 index 00000000..14035e9e --- /dev/null +++ b/apps/course/migrations/0002_auto_20180126_1325.py @@ -0,0 +1,73 @@ +# Generated by Django 2.0.1 on 2018-01-26 13:25 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('course', '0001_initial'), + ] + + operations = [ + migrations.AlterModelOptions( + name='category', + options={'verbose_name': 'Категория', 'verbose_name_plural': 'Категории'}, + ), + migrations.AlterModelManagers( + name='category', + managers=[ + ], + ), + migrations.RenameField( + model_name='course', + old_name='background', + new_name='cover', + ), + migrations.RenameField( + model_name='course', + old_name='deferred_start', + new_name='deferred_start_at', + ), + migrations.RenameField( + model_name='course', + old_name='is_highlighted', + new_name='is_featured', + ), + migrations.RemoveField( + model_name='course', + name='created_at', + ), + migrations.RemoveField( + model_name='course', + name='update_at', + ), + migrations.AddField( + model_name='course', + name='author', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, to=settings.AUTH_USER_MODEL), + ), + migrations.AddField( + model_name='course', + name='duration', + field=models.IntegerField(default=0, verbose_name='Продолжительность курса'), + ), + migrations.AddField( + model_name='course', + name='is_infinite', + field=models.BooleanField(default=False), + ), + migrations.AddField( + model_name='course', + name='status', + field=models.PositiveSmallIntegerField(choices=[(0, 'Pending'), (1, 'Published'), (2, 'Archived')], default=0, verbose_name='Статус'), + ), + migrations.AddField( + model_name='course', + name='url', + field=models.URLField(default='', verbose_name='Ссылка'), + ), + ] diff --git a/apps/course/migrations/0003_auto_20180126_1347.py b/apps/course/migrations/0003_auto_20180126_1347.py new file mode 100644 index 00000000..58808dde --- /dev/null +++ b/apps/course/migrations/0003_auto_20180126_1347.py @@ -0,0 +1,25 @@ +# Generated by Django 2.0.1 on 2018-01-26 13:47 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('course', '0002_auto_20180126_1325'), + ] + + operations = [ + migrations.AddField( + model_name='course', + name='created_at', + field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now), + preserve_default=False, + ), + migrations.AddField( + model_name='course', + name='update_at', + field=models.DateTimeField(auto_now=True), + ), + ] diff --git a/apps/course/models.py b/apps/course/models.py index 2c3b1102..bc2f48fc 100644 --- a/apps/course/models.py +++ b/apps/course/models.py @@ -1,32 +1,55 @@ +import arrow from django.db import models from django.utils import timezone +from django.contrib.auth import get_user_model from .manager import CategoryQuerySet +User = get_user_model() + class Course(models.Model): + STATUS_CHOICES = ( + (0, 'Pending'), + (1, 'Published'), + (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("Краткое описание курса") - background = models.ImageField("Фон курса", upload_to='courses') + cover = models.ImageField("Фон курса", upload_to='courses') price = models.DecimalField("Цена курса", help_text="Если цены нету, то курс бесплатный", max_digits=10, decimal_places=2, null=True, blank=True) - is_highlighted = models.BooleanField(default=False) - deferred_start = models.DateTimeField("Отложенный запуск курса", help_text="Заполнить если курс отложенный", 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) + is_featured = models.BooleanField(default=False) + url = models.URLField('Ссылка', default='') + status = models.PositiveSmallIntegerField('Статус', default=0, choices=STATUS_CHOICES) - created_at = models.DateTimeField(auto_created=True) + created_at = models.DateTimeField(auto_now_add=True) update_at = models.DateTimeField(auto_now=True) + @property def is_free(self): if self.price: return False return True + @property + def deferred_start_at_humanize(self): + return arrow.get(self.deferred_start_at).humanize(locale='ru') + + @property + def created_at_humanize(self): + return arrow.get(self.created_at).humanize(locale='ru') + + @property def is_deferred_start(self): - if not self.deferred_start: + if not self.deferred_start_at: return False - if timezone.now() < self.deferred_start: + if timezone.now() < self.deferred_start_at: return True return False @@ -38,7 +61,9 @@ class Course(models.Model): class Category(models.Model): title = models.CharField("Название категории", max_length=100) - manager = CategoryQuerySet.as_manager() - def __str__(self): return self.title + + class Meta: + verbose_name = "Категория" + verbose_name_plural = "Категории" diff --git a/apps/course/templates/course/_items.html b/apps/course/templates/course/_items.html index 331cd73e..0d876ccb 100644 --- a/apps/course/templates/course/_items.html +++ b/apps/course/templates/course/_items.html @@ -1,19 +1,19 @@ {% load static %} -
+
Подробнее
- {% if course.is_highlighted %} + {% if course.is_featured %}
{% endif %} {% if course.is_deferred_start %}
До запуска курса осталось:
-
16 часов 13 минут
+
{{ course.deferred_start_at_humanize }}
{% endif %}
-
АНИМАЦИЯ +
{{ course.category | upper }} {% if not course.is_free %}
{{ course.price|floatformat:"-2" }}$
{% endif %}
{{ course.title }} @@ -22,9 +22,9 @@
-
Александра Неимоверноумная
+
{{ course.author.first_name }} {{ course.author.last_name }}
-
SEPT 12, 2017
+
{{ course.created_at_humanize }}
diff --git a/project/templates/lilcity/main.html b/project/templates/lilcity/main.html new file mode 100644 index 00000000..68994872 --- /dev/null +++ b/project/templates/lilcity/main.html @@ -0,0 +1,575 @@ +{% extends "templates/lilcity/index.html" %} {% load static %} + +{% block title %}School LIL.CITY{% endblock title %} +{% block content %} +
+
+
Первая онлайн-школа креативного мышления для детей! 5+
+ КУПИТЬ ДОСУП ЗА 2000р. в мес. +
+
+
+
+
+

Каждый день, с понедельника по пятницу в 17:00 по московскому времени мы встречаемся в прямом эфире.

+

Пять предметов на каждый день: Персонаж, Развитие креативного мышления, Акварель, Пластилиновая живопись и История + искусств.

+ +
+
О школе
+
+
+ +
+
+
+

С раннего возраста мы стремимся развить в детях креативность, умение думать и анализировать, работать в смешанных + техниках и всевозможными материалами. Каждый урок интересный и уникальный.

+

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

+

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

+
+
- Sasha Kru, CEO и основатель + Lil.City +
+ + + + + + +
Другие видео смотрите на нашем + канале +
+
+
+
+
+ +
+
ПРЯМОЙ ЭФИР
+
Каждый день в 17.00 (по Мск)
+
Кроме выходных. Запись эфира доступна в течение 24-х часов.
+
+ + + СМОТРЕТЬ ПРИМЕР ЭФИРА
+
+
+
+
+
Преимущества
+
+

Если цените время и стремитесь быть продуктивными, то онлайн-образование это выбор прогрессивного человека для достижения + необходимых результатов.

+ +
+
+
+
+ + + +
+
Доступность
+
Учитесь, не выходя из дома. С активной жизнью в больших городах, времени для образование остается не много. + Маленьким городам, наоборот, не хватает разнообразия мегаполисов.
+
+
+
+ + + +
+
Стоимость
+
Онлайн-образование дешевле. Здесь не требуется аренда помещения, нет коммунальных платежей.
+
+
+
+ + + +
+
Свобода перемещений
+
Это важный критерий для родителей. С онлайн-образованием собирать, одевать и стоять в бесконечных пробках теперь + не нужно.
+
+
+
+ + + +
+
Выбор преподавателя
+
Личные аккаунты Инстаграм также доступны, чтобы узнать о творчестве, мыслях и интересах. Принять решение у какого + преподавателя учиться теперь просто.
+
+
+
+

И, наконец, учиться онлайн можете в пижаме, без макияжа и с огурцами на лице!

+
+
+
+
+
+
Отзывы
+
Мы получаем сотни тёплых отзывов от довольных родителей. Их можно почитать + здесь;) +
+
+
+
+ +
+
+
@redanna333
+
Мой ребёнок зарисовал!!! Хотя, я и не ставила таких глобальных целей, участвуя в этом лагере, просто занять дитё + чем-то творческим хоть иногда, но он реально рисует, сам, и не надо приглашать и уговаривать, просто берёт и + рисует) Спасибо, Саша, от всей души) Надеемся на встречу в школе)
+
+
+
+
+ +
+
+
@redanna333
+
Саша, огромное спасибо за ещё одну возможность погружения в удивительный мир Ваших уроков! С начала первого летнего + лагеря и до сегодняшнего дня, был запущен творческий круговорот разных идей, по заданиям и просто так)). На самом + деле, удивительная способность, находясь далеко, по другую сторону экрана, создавать уникальный контакт присутствия + рядом, будто в одной комнате и давно знакомы). И ещё одно важное качество- быть на стороне ребёнка в непростом + творческом процессе- моя дочь, слушая Ваше задание, расправляет "крылья", не боясь оценочного мнения , а сосредоточившись + на задаче)). P.S В школу идём без сомнений!
+
+
+
+
+ +
+
+
@redanna333
+
Саша, 👋 Вы потрясающе четко и качественно можете объяснить задание урока! Дети настолько увлекаются процессом, + что взрослые и сами включаются в эту интересную игру ТВОРЧЕСТВО! Спасибо Вам за Вдохновение, Любовь и желание + творить Чудеса! Темыч теперь легко может начать рисовать "трудные" картинки, потому что тетя Саша сказала: "все + состоит из простых форм!" Теперь это наш девиз) главное ушёл страх, что не выйдет ПРАВИЛЬНО, потому что нет ограничений + и правил в творчестве😜🙌надеемся на скорую встречу!!!
+
+
+
+
+
+
+
+
Галерея
+
+

Тысячи шедевров уже созданы благодаря Lil City School. Более 10000 работ можно + увидеть в Инстаграм

+ +
+ +
+
+
+
+
+
ПРИЛОЖЕНИЯ LIL CITY
+
Лучшие работы попадают в приложение Lil World
+
Lil World – это арт-фото редактор многократно отмеченный AppStore по всему миру как лучшее приложение с огромной коллекцией + иллюстраций стикеров. Украшайте ваши фото и превращайте их в волшебные миры.
+ +
+
+
+ +
+
+
+
+
+
+
Преподаватели
+
+

Преподаватели Lil City School имеют большой опыт, поэтому с первых минут детям будет интересно с нами.

+ +
+
+
+
+ +
+
+
Саша Крю, + #lil_персонаж +
+
@sashakru
+
+

Закончила ПХУ им К.А.Савицкого художник театра и кино. Работала с крупнейшими российскими и зарубежными + издательствами.

+

Участник и победитель международных выставок.

+

Основатель компании "Lil City".

+
+
+
+
+
+ +
+
+
Саша Крю, + #lil_персонаж +
+
@sashakru
+
+

Закончила ПХУ им К.А.Савицкого художник театра и кино. Работала с крупнейшими российскими и зарубежными + издательствами.

+

Участник и победитель международных выставок.

+

Основатель компании "Lil City".

+
+
+
+
+
+ +
+
+
Саша Крю, + #lil_персонаж +
+
@sashakru
+
+

Закончила ПХУ им К.А.Савицкого художник театра и кино. Работала с крупнейшими российскими и зарубежными + издательствами.

+

Участник и победитель международных выставок.

+

Основатель компании "Lil City".

+
+
+
+
+
+ +
+
+
Саша Крю, + #lil_персонаж +
+
@sashakru
+
+

Закончила ПХУ им К.А.Савицкого художник театра и кино. Работала с крупнейшими российскими и зарубежными + издательствами.

+

Участник и победитель международных выставок.

+

Основатель компании "Lil City".

+
+
+
+
+
Если хотите к нам в команду, то ждем ваше резюме + на почту +
+
+
+
+
+
Расписание
+
+
+
Понедельник
+
+
Персонаж.
+
Учимся создавать персонажей из простых форм. Изучаем характеры и эмоции.
+
+ +
Cамое главное - иметь альбом или блокнот с пустыми страницами (без линий и клеток) плотной гладкой бумагой, формат + А4. Рисовать будем цветными карандашами, а также простым, мягкостью B2. Иногда пригодятся вырезки из журналов + и клей-карандаш.
+
+
+
+
+
Вторник
+
+
Персонаж.
+
Учимся создавать персонажей из простых форм. Изучаем характеры и эмоции.
+
+ +
Cамое главное - иметь альбом или блокнот с пустыми страницами (без линий и клеток) плотной гладкой бумагой, формат + А4. Рисовать будем цветными карандашами, а также простым, мягкостью B2. Иногда пригодятся вырезки из журналов + и клей-карандаш.
+
+
+
+
+
Среда
+
+
Персонаж.
+
Учимся создавать персонажей из простых форм. Изучаем характеры и эмоции.
+
+ +
Cамое главное - иметь альбом или блокнот с пустыми страницами (без линий и клеток) плотной гладкой бумагой, формат + А4. Рисовать будем цветными карандашами, а также простым, мягкостью B2. Иногда пригодятся вырезки из журналов + и клей-карандаш.
+
+
+
+
+
Четверг
+
+
Персонаж.
+
Учимся создавать персонажей из простых форм. Изучаем характеры и эмоции.
+
+ +
Cамое главное - иметь альбом или блокнот с пустыми страницами (без линий и клеток) плотной гладкой бумагой, формат + А4. Рисовать будем цветными карандашами, а также простым, мягкостью B2. Иногда пригодятся вырезки из журналов + и клей-карандаш.
+
+
+
+
+
Пятница
+
+
Персонаж.
+
Учимся создавать персонажей из простых форм. Изучаем характеры и эмоции.
+
+ +
Cамое главное - иметь альбом или блокнот с пустыми страницами (без линий и клеток) плотной гладкой бумагой, формат + А4. Рисовать будем цветными карандашами, а также простым, мягкостью B2. Иногда пригодятся вырезки из журналов + и клей-карандаш.
+
+
+
+
+
+ Распечатать расписание чтобы не забыть
+
+
+
+
+
Онлайн-курсы
+
Помимо онлайн-школы Lil City у нас есть отдельные + курсы в записи. Учитесь и развивайте креативное мышление когда вам удобно.
+
+
+
+ + +
Подробнее
+
+
+
+ АНИМАЦИЯ +
30$
+
+ Базовый курс для детей по основам иллюстрации +
Этот курс поможет детям узнать о том как из простых форм создавать веселый и харизматичных персонажей.
+
+
+ +
+
+
Александра Неимоверноумная
+
+
SEPT 12, 2017
+ +
+
+
+
+
+ + +
Подробнее
+
+
До запуска курса осталось:
+
16 часов 13 минут
+
+
+
+
+ АНИМАЦИЯ +
30$
+
+ Базовый курс для детей по основам иллюстрации +
Этот курс поможет детям узнать о том как из простых форм создавать веселый и харизматичных персонажей.
+
+
+ +
+
+
Александра Неимоверноумная
+
+
SEPT 12, 2017
+ +
+
+
+
+
+ + +
Подробнее
+
+
+ АНИМАЦИЯ +
30$
+
+ Базовый курс для детей по основам иллюстрации +
Этот курс поможет детям узнать о том как из простых форм создавать веселый и харизматичных персонажей.
+
+
+ +
+
+
Александра Неимоверноумная
+
+
SEPT 12, 2017
+ +
+
+
+
+
+ +
+
+
+
+
+
+
LILCITY
+
Приложения, развивающие игры и интерактивные книги от Lil City.
+ УЗНАТЬ БОЛЬШЕ +
+
+
+ +
+
+
+
+
Наши партнеры
+ +
+
+{% endblock content %} \ No newline at end of file diff --git a/project/urls.py b/project/urls.py index af884c32..ed5cd1dc 100644 --- a/project/urls.py +++ b/project/urls.py @@ -24,7 +24,7 @@ urlpatterns = [ path('admin/', admin.site.urls), path('auth/', include(('apps.auth.urls', 'lilcity'))), path('courses/', CoursesView.as_view(), name='courses'), - path('', TemplateView.as_view(template_name="templates/lilcity/index.html"), name='index'), + path('', TemplateView.as_view(template_name="templates/lilcity/main.html"), name='index'), ] diff --git a/requirements.txt b/requirements.txt index 6b16ecce..17ee0f7c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,3 +7,5 @@ psycopg2==2.7.3.2 facepy==1.0.9 Pillow==5.0.0 django-active-link==0.1.2 +arrow==0.12.1 +django-filter==2.0.0.dev1 diff --git a/web/build/img/sprite.svg b/web/build/img/sprite.svg old mode 100755 new mode 100644