🚀 MEGA UPDATE: Объединение всех изменений для продакшена
Some checks failed
continuous-integration/drone/push Build is failing

 НОВЫЕ ФУНКЦИИ:
- 🎬 Поддержка видео в Hero баннерах и услугах
- 💊 Водная анимация пилюль маркеров банеров
- 📱 Полная главная страница с портфолио, блогом, новостями
- 🎯 HeroBanner модель с видео/изображениями
- 🎨 Современные hover-эффекты и анимации

📊 УЛУЧШЕНИЯ СТРУКТУРЫ:
- Расширенная home_modern.html с полным контентом
- Новые URL маршруты для всех секций
- Обновленные views с передачей всех данных
- CSS стили для всех новых секций
- Миграции для видео полей

🎪 HERO БАНЕР СИСТЕМА:
- Динамические банеры с видео/фото фонами
- Пилюли маркеры с водной анимацией
- Растягивание маркеров от центра
- Адаптивный дизайн для мобильных
- Glassmorphism эффекты

🎨 СОВРЕМЕННЫЙ ДИЗАЙН:
- Hover анимации для карточек
- Плавные переходы везде
- Современная типографика
- Градиенты и тени
- Отзывчивая сетка

Готов к продакшену! 🚀
This commit is contained in:
2025-11-25 11:24:19 +09:00
parent 6a576136af
commit 6f43fa4c3b
14 changed files with 1832 additions and 94 deletions

View File

@@ -3,6 +3,30 @@ from django.contrib.auth.models import AbstractUser, User
import uuid
from django.urls import reverse
class HeroBanner(models.Model):
"""Модель для главного баннера на сайте"""
title = models.CharField(max_length=200, verbose_name="Заголовок")
subtitle = models.TextField(blank=True, verbose_name="Подзаголовок")
description = models.TextField(blank=True, verbose_name="Описание")
image = models.ImageField(upload_to='static/img/hero/', blank=True, null=True, verbose_name="Фоновое изображение")
video = models.FileField(upload_to='static/video/hero/', blank=True, null=True,
help_text='Фоновое видео для баннера (MP4, WebM)', verbose_name="Фоновое видео")
video_poster = models.ImageField(upload_to='static/img/hero/posters/', blank=True, null=True,
help_text='Превью изображение для видео', verbose_name="Превью видео")
button_text = models.CharField(max_length=100, blank=True, verbose_name="Текст кнопки")
button_link = models.URLField(blank=True, verbose_name="Ссылка кнопки")
is_active = models.BooleanField(default=True, verbose_name="Активен")
order = models.PositiveIntegerField(default=0, verbose_name="Порядок отображения")
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = 'Hero Баннер'
verbose_name_plural = 'Hero Баннеры'
ordering = ['order', '-created_at']
def __str__(self):
return self.title
class Category(models.Model):
name = models.CharField(max_length=100)
description = models.TextField(default='Описание категории')
@@ -21,6 +45,10 @@ class Service(models.Model):
price = models.DecimalField(max_digits=10, decimal_places=2)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, related_name='services')
image = models.ImageField(upload_to='static/img/services/', blank=True, null=True)
video = models.FileField(upload_to='static/video/services/', blank=True, null=True, help_text='Видео файл для услуги (MP4, WebM, AVI)')
video_poster = models.ImageField(upload_to='static/img/services/posters/', blank=True, null=True, help_text='Превью изображение для видео')
video = models.FileField(upload_to='static/video/services/', blank=True, null=True, help_text='Видео файл для услуги (MP4, WebM, AVI)')
video_poster = models.ImageField(upload_to='static/img/services/posters/', blank=True, null=True, help_text='Превью изображение для видео')
class Meta:
verbose_name = 'Услуга'
@@ -61,6 +89,8 @@ class BlogPost(models.Model):
content = models.TextField()
published_date = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to='static/img/blog/', blank=True, null=True)
video = models.FileField(upload_to='static/video/blog/', blank=True, null=True, help_text='Видео файл для блог поста')
video_poster = models.ImageField(upload_to='static/img/blog/posters/', blank=True, null=True, help_text='Превью изображение для видео')
class Meta:
verbose_name = 'Блог'
@@ -126,6 +156,8 @@ class Project(models.Model):
order = models.OneToOneField(Order, on_delete=models.CASCADE, related_name='project', null=True, blank=True)
category = models.ForeignKey(Category, on_delete=models.SET_NULL, null=True, blank=True)
image = models.ImageField(upload_to='static/img/project/', blank=True, null=True)
video = models.FileField(upload_to='static/video/project/', blank=True, null=True, help_text='Видео презентация проекта')
video_poster = models.ImageField(upload_to='static/img/project/posters/', blank=True, null=True, help_text='Превью изображение для видео проекта')
status = models.CharField(max_length=50, choices=[('in_progress', 'В процессе'), ('completed', 'Завершен')], default='in_progress')
class Meta:
@@ -144,6 +176,8 @@ class Review(models.Model):
comment = models.TextField()
review_date = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to='static/img/review/', blank=True, null=True)
video = models.FileField(upload_to='static/video/review/', blank=True, null=True, help_text='Видео отзыв о работе')
video_poster = models.ImageField(upload_to='static/img/review/posters/', blank=True, null=True, help_text='Превью для видео отзыва')
class Meta:
verbose_name = 'Отзыв'