Добавлена система проектов с автоматическим ресайзом изображений и адаптивным дизайном
Some checks failed
continuous-integration/drone/push Build is failing

- Удалена старая система портфолио (PortfolioCategory, PortfolioItem)
- Расширена модель Project: slug, categories (M2M), thumbnail, media files, meta fields
- Объединены категории: ProjectCategory удалена, используется общая Category
- Автоматический ресайз thumbnail до 600x400px с умным кропом по центру
- Создан /projects/ - страница списка проектов с фильтрацией по категориям
- Создан /project/<pk>/ - детальная страница проекта с галереей Swiper
- Адаптивный дизайн: 3 карточки в ряд (десктоп), 2 (планшет), 1 (мобильный)
- Параллакс-эффект на изображениях при наведении
- Lazy loading для оптимизации загрузки
- Фильтры категорий в виде пилюль как на странице услуг
- Компактные карточки с фиксированной шириной
- Кликабельные проекты в service_detail с отображением всех медиа
This commit is contained in:
2025-11-26 09:44:14 +09:00
parent 5bcf3e8198
commit e7d6d5262d
26 changed files with 3029 additions and 447 deletions

View File

@@ -1,5 +1,9 @@
from django.shortcuts import render, get_object_or_404, redirect
from .models import Service, Project, Client, BlogPost, Review, Order, ServiceRequest, HeroBanner, Category, ContactInfo, Team, Career
from .models import (
Service, Project, Client, BlogPost, Review, Order, ServiceRequest,
HeroBanner, Category, ContactInfo, Team, Career,
ProjectMedia
)
from django.db.models import Avg
from comunication.models import TelegramSettings
import qrcode
@@ -75,7 +79,45 @@ def service_detail(request, pk):
def project_detail(request, pk):
project = get_object_or_404(Project, pk=pk)
return render(request, 'web/project_detail.html', {'project': project})
# Увеличиваем счётчик просмотров
project.views_count += 1
project.save(update_fields=['views_count'])
# Получаем похожие проекты (той же категории или сервиса)
similar_projects = Project.objects.filter(
status='completed'
).exclude(pk=project.pk)
if project.category:
similar_projects = similar_projects.filter(category=project.category)
elif project.service:
similar_projects = similar_projects.filter(service=project.service)
similar_projects = similar_projects[:3]
return render(request, 'web/project_detail.html', {
'project': project,
'similar_projects': similar_projects
})
def projects_list(request):
"""Список всех завершённых проектов"""
projects = Project.objects.filter(status='completed').order_by('-is_featured', '-display_order', '-completion_date')
# Фильтр по категории
category_id = request.GET.get('category')
if category_id:
projects = projects.filter(categories__id=category_id)
# Получаем все категории с проектами
categories = Category.objects.filter(projects__status='completed').distinct().order_by('order', 'name')
return render(request, 'web/projects_list.html', {
'projects': projects,
'categories': categories,
'selected_category': category_id
})
def client_detail(request, pk):
client = get_object_or_404(Client, pk=pk)
@@ -108,9 +150,6 @@ def about_view(request):
contact_info = ContactInfo.get_active()
return render(request, 'web/about.html', {'contact_info': contact_info})
def portfolio_view(request):
projects = Project.objects.all()
return render(request, 'web/portfolio.html', {'projects': projects})
def blog_view(request):
blog_posts = BlogPost.objects.all().order_by('-created_at')