страница с ценами

remotes/origin/feature/packages-page-1-08-19
gzbender 7 years ago
parent e2c46af6a2
commit 8518d915df
  1. 9
      api/v1/serializers/content.py
  2. 3
      api/v1/urls.py
  3. 9
      api/v1/views.py
  4. 7
      apps/content/admin.py
  5. 38
      apps/content/migrations/0029_auto_20190730_2032.py
  6. 21
      apps/content/models.py
  7. 44
      project/templates/lilcity/packages.html
  8. 3
      project/urls.py
  9. 12
      project/views.py
  10. 54
      web/src/sass/_common.sass

@ -4,7 +4,7 @@ from django.conf import settings
from apps.content.models import ( from apps.content.models import (
Banner, Content, Image, Text, ImageText, Video, Banner, Content, Image, Text, ImageText, Video,
Gallery, GalleryImage, ImageObject, FAQ) Gallery, GalleryImage, ImageObject, FAQ, Package)
from . import Base64ImageField from . import Base64ImageField
@ -268,3 +268,10 @@ class FAQSerializer(serializers.ModelSerializer):
class Meta: class Meta:
model = FAQ model = FAQ
fields = '__all__' fields = '__all__'
class PackageSerializer(serializers.ModelSerializer):
class Meta:
model = Package
fields = '__all__'

@ -19,7 +19,7 @@ from .views import (
SchoolScheduleViewSet, LiveLessonViewSet, SchoolScheduleViewSet, LiveLessonViewSet,
PaymentViewSet, ObjectCommentsViewSet, PaymentViewSet, ObjectCommentsViewSet,
ContestViewSet, ContestWorkViewSet, NotifiedAboutBonuses, ContestViewSet, ContestWorkViewSet, NotifiedAboutBonuses,
AuthorBalanceUsersViewSet, CaptureEmail, FAQViewSet, UserGalleryViewSet, BonusesViewSet) AuthorBalanceUsersViewSet, CaptureEmail, FAQViewSet, UserGalleryViewSet, BonusesViewSet, PackageViewSet)
router = DefaultRouter() router = DefaultRouter()
router.register(r'author-requests', AuthorRequestViewSet, base_name='author-requests') router.register(r'author-requests', AuthorRequestViewSet, base_name='author-requests')
@ -48,6 +48,7 @@ router.register(r'users', UserViewSet, base_name='users')
router.register(r'user-gallery', UserGalleryViewSet, base_name='user-gallery') router.register(r'user-gallery', UserGalleryViewSet, base_name='user-gallery')
router.register(r'contests', ContestViewSet, base_name='contests') router.register(r'contests', ContestViewSet, base_name='contests')
router.register(r'contest-works', ContestWorkViewSet, base_name='contest_works') router.register(r'contest-works', ContestWorkViewSet, base_name='contest_works')
router.register(r'packages', PackageViewSet, base_name='packages')
# router.register(r'configs', ConfigViewSet, base_name='configs') # router.register(r'configs', ConfigViewSet, base_name='configs')

@ -30,7 +30,7 @@ from .serializers.content import (
VideoSerializer, VideoCreateSerializer, VideoSerializer, VideoCreateSerializer,
GallerySerializer, GallerySerializer,
GalleryImageSerializer, GalleryImageCreateSerializer, GalleryImageSerializer, GalleryImageCreateSerializer,
ImageObjectSerializer, FAQSerializer, ImageObjectSerializer, FAQSerializer, PackageSerializer,
) )
from .serializers.school import ( from .serializers.school import (
SchoolScheduleSerializer, SchoolScheduleSerializer,
@ -65,7 +65,7 @@ from apps.config.models import Config
from apps.content.models import ( from apps.content.models import (
Banner, Image, Text, ImageText, Video, Banner, Image, Text, ImageText, Video,
Gallery, GalleryImage, ImageObject, Gallery, GalleryImage, ImageObject,
Contest, ContestWork, FAQ) Contest, ContestWork, FAQ, Package)
from apps.payment.models import ( from apps.payment.models import (
AuthorBalance, Payment, AuthorBalance, Payment,
CoursePayment, SchoolPayment, UserBonus, CoursePayment, SchoolPayment, UserBonus,
@ -774,3 +774,8 @@ class NotifiedAboutBonuses(views.APIView):
b.save() b.save()
return Response({'status': 'ok'}) return Response({'status': 'ok'})
class PackageViewSet(ExtendedModelViewSet):
queryset = Package.objects.all()
serializer_class = PackageSerializer
permission_classes = (IsAdmin,)

@ -8,7 +8,7 @@ from polymorphic.admin import (
from apps.content.models import ( from apps.content.models import (
Banner, Content, Image, Text, ImageText, Video, Banner, Content, Image, Text, ImageText, Video,
Gallery, GalleryImage, ImageObject, Gallery, GalleryImage, ImageObject,
Contest, ContestWork, FAQ, Contest, ContestWork, FAQ, Package,
) )
@ -99,3 +99,8 @@ class ContestWorkAdmin(admin.ModelAdmin):
@admin.register(FAQ) @admin.register(FAQ)
class FAQAdmin(admin.ModelAdmin): class FAQAdmin(admin.ModelAdmin):
base_model = FAQ base_model = FAQ
@admin.register(Package)
class PackageAdmin(admin.ModelAdmin):
base_model = Package

@ -0,0 +1,38 @@
# Generated by Django 2.0.7 on 2019-07-30 20:32
import django.contrib.postgres.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('content', '0028_auto_20190726_0106'),
]
operations = [
migrations.CreateModel(
name='Package',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('price', models.DecimalField(decimal_places=2, max_digits=10)),
('high_price', models.DecimalField(blank=True, decimal_places=2, max_digits=10, null=True)),
('description', models.TextField(db_index=True, default='', verbose_name='Описание')),
('duration', models.PositiveSmallIntegerField()),
('options', models.TextField(db_index=True, default='', verbose_name='Описание')),
],
options={
'ordering': ('duration',),
},
),
migrations.AlterField(
model_name='banner',
name='main_banner',
field=django.contrib.postgres.fields.ArrayField(base_field=models.IntegerField(choices=[(1, 'Главная'), (2, 'Курсы'), (3, 'Школа'), (4, 'Пакеты')]), blank=True, default=[], size=None),
),
migrations.AlterField(
model_name='banner',
name='pages',
field=django.contrib.postgres.fields.ArrayField(base_field=models.IntegerField(choices=[(1, 'Главная'), (2, 'Курсы'), (3, 'Школа'), (4, 'Пакеты')]), blank=True, default=[], size=None),
),
]

@ -146,11 +146,13 @@ class Banner(models.Model):
PAGE_INDEX = 1 PAGE_INDEX = 1
PAGE_COURSES = 2 PAGE_COURSES = 2
PAGE_SCHOOL = 3 PAGE_SCHOOL = 3
PAGE_PACKAGES = 4
PAGE_CHOICES = ( PAGE_CHOICES = (
(PAGE_INDEX, 'Главная'), (PAGE_INDEX, 'Главная'),
(PAGE_COURSES, 'Курсы'), (PAGE_COURSES, 'Курсы'),
(PAGE_SCHOOL, 'Школа'), (PAGE_SCHOOL, 'Школа'),
(PAGE_PACKAGES, 'Пакеты')
) )
text = models.TextField(blank=True, default='') text = models.TextField(blank=True, default='')
@ -241,3 +243,22 @@ class ContestWork(models.Model):
class FAQ(models.Model): class FAQ(models.Model):
question = models.TextField(max_length=1000,) question = models.TextField(max_length=1000,)
answer = models.TextField(max_length=1000,) answer = models.TextField(max_length=1000,)
class Package(models.Model):
price = models.DecimalField(max_digits=10, decimal_places=2,)
high_price = models.DecimalField(max_digits=10, decimal_places=2, null=True, blank=True)
description = models.TextField(
'Описание', default='', db_index=True
)
duration = models.PositiveSmallIntegerField()
options = models.TextField(
'Опции', default='', db_index=True
)
class Meta:
ordering = ('duration',)
@property
def options_html(self):
return ''.join(map(lambda x: '<p>%s</p>' % x, self.options.split('\n')))

@ -0,0 +1,44 @@
{% extends "templates/lilcity/index.html" %}
{% load static %}
{% load ruplural from plural %}
{% block content %}
<div class="section">
<div class="section__center center">
<div class="packages">
{% for package in packages %}
<div class="package">
<div class="package__title subtitle">
{% if package.duration == 12 %}
<b>1</b>&nbsp;год
{% else %}
<b>{{ package.duration }}</b>&nbsp;{{ package.duration|ruplural:"месяц,месяца,месяцев" }}
{% endif %}
</div>
<div class="package__desc">{{ package.description }}</div>
<div class="package__price">
{{ package.price|floatformat }}р
{% if package.high_price %}
<div class="package__high-price">&nbsp;{{ package.high_price|floatformat }}р&nbsp;</div>
{% endif %}
</div>
<div class="package__options">
<b>Включает</b>
<div>{{ package.options_html|safe }}</div>
</div>
<div>
<a href="#" class="package__btn btn {% if forloop.counter == 2 %}btn_light{% endif %}"
{% if forloop.counter == 1 %}
style="background-image: linear-gradient(104deg, #f8f8f8, #fff2f2)"
{% endif %}
{% if forloop.counter == 4 %}
style="background-image: linear-gradient(to bottom, #ffe790, #f9d055 45%, #f9c155); padding: 12px 9px;"
{% endif %}
>{% if forloop.counter == 4 %}Вступить в Lil-Клуб{% else %}Купить{% endif %}</a>
</div>
</div>
{% endfor %}
</div>
</div>
</div>
{% endblock content %}

@ -37,7 +37,7 @@ from apps.payment.views import (
SchoolBuyView, GiftCertificatesView, GiftCertificateBuyView, SchoolBuyView, GiftCertificatesView, GiftCertificateBuyView,
GiftCertificateBuySuccessView, GiftCertificateGetView, DrawingCampBuyView) GiftCertificateBuySuccessView, GiftCertificateGetView, DrawingCampBuyView)
from .views import AboutView, IndexView, SchoolSchedulesView, LinksView from .views import AboutView, IndexView, SchoolSchedulesView, LinksView, PackagesView
# TODO trim slash in the end # TODO trim slash in the end
urlpatterns = [ urlpatterns = [
@ -103,6 +103,7 @@ urlpatterns = [
path('gift-certificate/<str:slug>/get', GiftCertificateGetView.as_view(), name='gift-certificate-get'), path('gift-certificate/<str:slug>/get', GiftCertificateGetView.as_view(), name='gift-certificate-get'),
path('faq', FAQView.as_view(), name='faq'), path('faq', FAQView.as_view(), name='faq'),
path('links', LinksView.as_view(), name='links'), path('links', LinksView.as_view(), name='links'),
path('packages', PackagesView.as_view(), name='packages'),
] ]

@ -11,7 +11,7 @@ from paymentwall.pingback import Pingback
from apps.course.models import Course from apps.course.models import Course
from apps.school.models import SchoolSchedule from apps.school.models import SchoolSchedule
from apps.payment.models import SchoolPayment, UserGiftCertificate, Payment, DrawingCampPayment from apps.payment.models import SchoolPayment, UserGiftCertificate, Payment, DrawingCampPayment
from apps.content.models import Banner from apps.content.models import Banner, Package
User = get_user_model() User = get_user_model()
@ -142,3 +142,13 @@ class SchoolSchedulesView(TemplateView):
class LinksView(TemplateView): class LinksView(TemplateView):
template_name = 'templates/lilcity/links.html' template_name = 'templates/lilcity/links.html'
class PackagesView(TemplateView):
template_name = 'templates/lilcity/packages.html'
def get_context_data(self):
context = super().get_context_data()
context['packages'] = Package.objects.all()[:4]
context['banners'] = Banner.get_for_page(Banner.PAGE_PACKAGES)[:1]
return context

@ -4837,3 +4837,57 @@ a
padding-top: 80px padding-top: 80px
min-height: 200px min-height: 200px
padding-bottom: 60px padding-bottom: 60px
.packages
display: flex
overflow-x: auto
background: white
padding: 30px
margin: -50px
.package
border-radius: 10px
box-shadow: 0 10px 30px 0 rgba(0, 0, 0, 0.1)
margin-right: 20px
padding: 20px
width: calc(25% - 20px)
display: flex
flex-direction: column
text-align: center
&__btn
width: 100%
&__title
font-size: 14px
text-align: center
margin-top: 20px
font-family: 'ProximaNova-Regular', sans-serif
&__desc
font-size: 13px
height: 35px
&__price
font-size: 40px
margin: 20px 0 40px
&__high-price
text-decoration: line-through
font-size: 15px
color: #9b9b9b
height: 15px
margin-bottom: -15px
&__options
padding: 30px 0
border-image-source: linear-gradient(to right, #ffe2eb, #d8f5f5)
border-image-slice: 1
border-top: 1px solid
text-align: left
font-size: 12px
line-height: 18px
flex: 1
& p
margin-top: 6px

Loading…
Cancel
Save