diff --git a/.gitignore b/.gitignore index de8f1ab9..944152f8 100644 --- a/.gitignore +++ b/.gitignore @@ -109,4 +109,5 @@ venv.bak/ # JavaScript .map -node_modules \ No newline at end of file +node_modules +db.sqlite3 \ No newline at end of file diff --git a/apps/course/__init__.py b/apps/course/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/course/admin.py b/apps/course/admin.py new file mode 100644 index 00000000..1fc02ef1 --- /dev/null +++ b/apps/course/admin.py @@ -0,0 +1,13 @@ +from django.contrib import admin + +from .models import Course, Category + + +@admin.register(Course) +class CourseAdmin(admin.ModelAdmin): + pass + + +@admin.register(Category) +class CategoryAdmin(admin.ModelAdmin): + pass diff --git a/apps/course/apps.py b/apps/course/apps.py new file mode 100644 index 00000000..70a0c55c --- /dev/null +++ b/apps/course/apps.py @@ -0,0 +1,6 @@ +from django.apps import AppConfig + + +class CourseConfig(AppConfig): + name = 'apps.course' + label = 'lilcity_course' diff --git a/apps/course/manager.py b/apps/course/manager.py new file mode 100644 index 00000000..76194ef8 --- /dev/null +++ b/apps/course/manager.py @@ -0,0 +1,6 @@ +from django.db import models + + +class CategoryQuerySet(models.QuerySet): + def all(self): + return self.filter() diff --git a/apps/course/migrations/0001_initial.py b/apps/course/migrations/0001_initial.py new file mode 100644 index 00000000..4c69bb32 --- /dev/null +++ b/apps/course/migrations/0001_initial.py @@ -0,0 +1,45 @@ +# Generated by Django 2.0.1 on 2018-01-22 11:43 + +from django.db import migrations, models +import django.db.models.deletion +import django.db.models.manager + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Category', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=100, verbose_name='Название категории')), + ], + managers=[ + ('manager', django.db.models.manager.Manager()), + ], + ), + migrations.CreateModel( + name='Course', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('created_at', models.DateTimeField(auto_created=True)), + ('title', models.CharField(max_length=100, verbose_name='Название курса')), + ('short_description', models.TextField(verbose_name='Краткое описание курса')), + ('background', models.ImageField(upload_to='courses', verbose_name='Фон курса')), + ('price', models.DecimalField(blank=True, decimal_places=2, help_text='Если цены нету, то курс бесплатный', max_digits=10, null=True, verbose_name='Цена курса')), + ('is_highlighted', models.BooleanField(default=False)), + ('deferred_start', models.DateTimeField(blank=True, help_text='Заполнить если курс отложенный', null=True, verbose_name='Отложенный запуск курса')), + ('update_at', models.DateTimeField(auto_now=True)), + ('category', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='course.Category')), + ], + options={ + 'verbose_name': 'Курс', + 'verbose_name_plural': 'Курсы', + }, + ), + ] diff --git a/apps/course/migrations/__init__.py b/apps/course/migrations/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/course/models.py b/apps/course/models.py new file mode 100644 index 00000000..2c3b1102 --- /dev/null +++ b/apps/course/models.py @@ -0,0 +1,44 @@ +from django.db import models +from django.utils import timezone + +from .manager import CategoryQuerySet + + +class Course(models.Model): + title = models.CharField("Название курса", max_length=100) + short_description = models.TextField("Краткое описание курса") + background = 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) + + category = models.ForeignKey("Category", on_delete=models.PROTECT) + + created_at = models.DateTimeField(auto_created=True) + update_at = models.DateTimeField(auto_now=True) + + def is_free(self): + if self.price: + return False + return True + + def is_deferred_start(self): + if not self.deferred_start: + return False + + if timezone.now() < self.deferred_start: + return True + return False + + class Meta: + verbose_name = "Курс" + verbose_name_plural = "Курсы" + + +class Category(models.Model): + title = models.CharField("Название категории", max_length=100) + + manager = CategoryQuerySet.as_manager() + + def __str__(self): + return self.title diff --git a/apps/course/templates/course/_items.html b/apps/course/templates/course/_items.html new file mode 100644 index 00000000..331cd73e --- /dev/null +++ b/apps/course/templates/course/_items.html @@ -0,0 +1,42 @@ +{% load static %} + +
+
Подробнее
+ {% if course.is_highlighted %} +
+ {% endif %} + {% if course.is_deferred_start %} +
+
До запуска курса осталось:
+
16 часов 13 минут
+
+
+ {% endif %} +
+
АНИМАЦИЯ + {% if not course.is_free %}
{{ course.price|floatformat:"-2" }}$
{% endif %} +
+ {{ course.title }} +
{{ course.short_description }} +
+
+
+
+
Александра Неимоверноумная
+
+
SEPT 12, 2017
+ +
+
+
+
\ No newline at end of file diff --git a/apps/course/templates/course/course_items.html b/apps/course/templates/course/course_items.html new file mode 100644 index 00000000..26a3377f --- /dev/null +++ b/apps/course/templates/course/course_items.html @@ -0,0 +1,4 @@ +{% for course in course_items %} + {% cycle '' 'theme_green' 'theme_violet' as theme_color silent %} + {% include "course/_items.html" %} +{% endfor %} \ No newline at end of file diff --git a/apps/course/templates/course/courses.html b/apps/course/templates/course/courses.html new file mode 100644 index 00000000..72a4c155 --- /dev/null +++ b/apps/course/templates/course/courses.html @@ -0,0 +1,53 @@ +{% extends "templates/lilcity/index.html" %} +{% load static %} +{% load category_items from lilcity_category %} + +{% block content %} +
+
+
Онлайн-курсы LilCity
+
+
+
+
+
+

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

+
+
Курсы
+
+
+
+
+
Категории
+
+ {% category_items %} +
+
+
+
+
+
+
+
+ {% include "course/course_items.html" %} +
+
+ {% if page_obj.has_next %} + + {% endif %} +
+
+
+
+
+
+
+
LILCITY
+
Приложения, развивающие игры и интерактивные книги от Lil City.
+ УЗНАТЬ БОЛЬШЕ
+
+
+
+{% endblock content %} \ No newline at end of file diff --git a/apps/course/templates/course/inclusion/category_items.html b/apps/course/templates/course/inclusion/category_items.html new file mode 100644 index 00000000..ec8397d9 --- /dev/null +++ b/apps/course/templates/course/inclusion/category_items.html @@ -0,0 +1,5 @@ +{% for category in category_items %} +
+
{{ category.title }}
+
+{% endfor %} \ No newline at end of file diff --git a/apps/course/templatetags/__init__.py b/apps/course/templatetags/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/apps/course/templatetags/lilcity_category.py b/apps/course/templatetags/lilcity_category.py new file mode 100644 index 00000000..1d8666c6 --- /dev/null +++ b/apps/course/templatetags/lilcity_category.py @@ -0,0 +1,11 @@ +from django import template + +from ..models import Category + + +register = template.Library() + + +@register.inclusion_tag('course/inclusion/category_items.html') +def category_items(): + return {"category_items": Category.manager.all()} diff --git a/apps/course/tests.py b/apps/course/tests.py new file mode 100644 index 00000000..7ce503c2 --- /dev/null +++ b/apps/course/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/apps/course/views.py b/apps/course/views.py new file mode 100644 index 00000000..03beac76 --- /dev/null +++ b/apps/course/views.py @@ -0,0 +1,14 @@ +from django.views.generic import ListView + +from .models import Course + + +class CoursesView(ListView): + model = Course + context_object_name = "course_items" + paginate_by = 6 + + def get_template_names(self): + if self.request.is_ajax(): + return 'course/course_items.html' + return "course/courses.html" diff --git a/docs/entities-diagram.png b/docs/entities-diagram.png deleted file mode 100644 index 06287181..00000000 Binary files a/docs/entities-diagram.png and /dev/null differ diff --git a/docs/overview.md b/docs/overview.md index f43e50f4..2d418b7d 100644 --- a/docs/overview.md +++ b/docs/overview.md @@ -45,4 +45,4 @@ CRUD для целей доступа к персистентным хранил ### Диаграмма сущностей проекта -![Диаграмма сущностей проекта.png](entities-diagram.png) \ No newline at end of file +Актуальная версия: [Google Drive](https://drive.google.com/file/d/1OPt3_M0VrVBkRK1M4LTLJ-UMFEwojMzc/view?usp=sharing) diff --git a/project/settings.py b/project/settings.py index 01e992e0..10946d9e 100644 --- a/project/settings.py +++ b/project/settings.py @@ -39,11 +39,13 @@ INSTALLED_APPS = [ 'django.contrib.staticfiles', ] + [ 'anymail', + 'active_link', ] + [ 'apps.auth.apps', 'apps.user', 'apps.notification', 'apps.payment', + 'apps.course', ] MIDDLEWARE = [ @@ -153,3 +155,5 @@ DEFAULT_FROM_EMAIL = "postmaster@mail.9ev.ru" TWILIO_ACCOUNT = 'ACdf4a96b776cc764bc3ec0f0e136ba550' TWILIO_TOKEN = '559a6b1fce121759c9af2dcbb3f755ea' TWILIO_FROM_PHONE = '+37128914409' + +ACTIVE_LINK_STRICT = True \ No newline at end of file diff --git a/project/templates/lilcity/index.html b/project/templates/lilcity/index.html index 186cc8b9..222a58d7 100644 --- a/project/templates/lilcity/index.html +++ b/project/templates/lilcity/index.html @@ -1,4 +1,6 @@ {% load static %} +{% load active_link_tags %} + @@ -52,7 +54,7 @@ - +