diff --git a/smartsoltech/smartsoltech/settings.py b/smartsoltech/smartsoltech/settings.py index f4959ca..e633236 100644 --- a/smartsoltech/smartsoltech/settings.py +++ b/smartsoltech/smartsoltech/settings.py @@ -72,6 +72,7 @@ TEMPLATES = [ 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', + 'web.context_processors.footer_settings', # Custom context processor ], }, }, diff --git a/smartsoltech/web/admin.py b/smartsoltech/web/admin.py index 29b0498..8a69a3f 100644 --- a/smartsoltech/web/admin.py +++ b/smartsoltech/web/admin.py @@ -1,5 +1,8 @@ from django.contrib import admin -from .models import Service, Project, Client, Order, Review, BlogPost, Category, ServiceRequest +from .models import ( + Service, Project, Client, Order, Review, BlogPost, + Category, ServiceRequest, AboutPage, FooterSettings +) from .forms import ProjectForm @admin.register(Service) @@ -45,4 +48,105 @@ class CategoryAdmin(admin.ModelAdmin): class ServiceRequestAdmin(admin.ModelAdmin): list_display = ('service','token', 'client', 'created_at') search_fields = ('service','token', 'client') - list_filter = ('service','token','client') \ No newline at end of file + list_filter = ('service','token','client') + +@admin.register(AboutPage) +class AboutPageAdmin(admin.ModelAdmin): + list_display = ('hero_title', 'is_active', 'updated_at') + list_filter = ('is_active', 'updated_at') + search_fields = ('hero_title', 'mission_title', 'vision_title') + + fieldsets = ( + ('Hero секция', { + 'fields': ('hero_badge', 'hero_title', 'hero_description') + }), + ('Статистика', { + 'fields': ('stat_projects', 'stat_clients', 'stat_years', 'stat_support') + }), + ('Миссия', { + 'fields': ( + 'mission_badge', 'mission_title', 'mission_description', + 'mission_point_1_title', 'mission_point_1_text', + 'mission_point_2_title', 'mission_point_2_text', + 'mission_point_3_title', 'mission_point_3_text', + ) + }), + ('Видение', { + 'fields': ('vision_badge', 'vision_title', 'vision_description') + }), + ('Навыки', { + 'fields': ( + 'skill_1_name', 'skill_1_percent', + 'skill_2_name', 'skill_2_percent', + 'skill_3_name', 'skill_3_percent', + 'skill_4_name', 'skill_4_percent', + ) + }), + ('Команда', { + 'fields': ('team_badge', 'team_title', 'team_description') + }), + ('Ценности', { + 'fields': ( + 'values_badge', 'values_title', + 'value_1_icon', 'value_1_title', 'value_1_text', + 'value_2_icon', 'value_2_title', 'value_2_text', + 'value_3_icon', 'value_3_title', 'value_3_text', + 'value_4_icon', 'value_4_title', 'value_4_text', + ) + }), + ('Контакты', { + 'fields': ('contact_title', 'contact_description') + }), + ('Настройки', { + 'fields': ('is_active',) + }), + ) + + def has_add_permission(self, request): + return not AboutPage.objects.filter(is_active=True).exists() + + +@admin.register(FooterSettings) +class FooterSettingsAdmin(admin.ModelAdmin): + list_display = ('company_name', 'email', 'is_active', 'updated_at') + list_filter = ('is_active', 'updated_at') + search_fields = ('company_name', 'email') + + fieldsets = ( + ('Информация о компании', { + 'fields': ('company_name', 'company_description', 'company_logo_icon') + }), + ('Социальные сети', { + 'fields': ('telegram_url', 'instagram_url', 'linkedin_url', 'github_url', 'facebook_url', 'twitter_url'), + 'classes': ('collapse',) + }), + ('Контактная информация', { + 'fields': ('email', 'phone', 'address') + }), + ('Меню футера', { + 'fields': ( + 'show_services_menu', 'services_title', + 'show_company_menu', 'company_menu_title' + ), + 'classes': ('collapse',) + }), + ('Copyright', { + 'fields': ('copyright_text',) + }), + ('Интеграция скриптов', { + 'fields': ('google_analytics', 'google_adsense', 'yandex_metrika', 'facebook_pixel'), + 'description': 'Вставьте коды аналитики без тегов ', + 'classes': ('collapse',) + }), + ('Дополнительные скрипты', { + 'fields': ('custom_head_scripts', 'custom_body_scripts'), + 'description': 'Вставьте дополнительные скрипты С тегами ', + 'classes': ('collapse',) + }), + ('Настройки', { + 'fields': ('is_active',) + }), + ) + + def has_add_permission(self, request): + return not FooterSettings.objects.filter(is_active=True).exists() diff --git a/smartsoltech/web/context_processors.py b/smartsoltech/web/context_processors.py new file mode 100644 index 0000000..dc83204 --- /dev/null +++ b/smartsoltech/web/context_processors.py @@ -0,0 +1,13 @@ +from .models import FooterSettings + + +def footer_settings(request): + """Context processor для настроек футера""" + try: + footer = FooterSettings.objects.filter(is_active=True).first() + except: + footer = None + + return { + 'footer_settings': footer + } diff --git a/smartsoltech/web/management/commands/init_about_footer.py b/smartsoltech/web/management/commands/init_about_footer.py new file mode 100644 index 0000000..a9c9efd --- /dev/null +++ b/smartsoltech/web/management/commands/init_about_footer.py @@ -0,0 +1,112 @@ +from django.core.management.base import BaseCommand +from web.models import AboutPage, FooterSettings + + +class Command(BaseCommand): + help = 'Создает начальные данные для страницы О нас и Footer' + + def handle(self, *args, **options): + # Создать About Page + if not AboutPage.objects.exists(): + AboutPage.objects.create( + hero_badge='🚀 О нас', + hero_title='Мы создаем цифровое будущее', + hero_description='SmartSolTech - это команда профессионалов, которые превращают идеи в инновационные IT-решения. Мы помогаем бизнесу расти и развиваться в цифровую эпоху.', + + stat_projects=50, + stat_clients=30, + stat_years=3, + stat_support='24/7', + + mission_badge='🎯 Наша миссия', + mission_title='Делаем технологии доступными', + mission_description='Мы верим, что каждый бизнес заслуживает доступа к современным технологиям. Наша миссия — демократизировать IT-решения и помочь компаниям любого размера достичь цифрового совершенства.', + + mission_point_1_title='Инновационные решения', + mission_point_1_text='Используем передовые технологии для создания уникальных продуктов', + + mission_point_2_title='Клиентоориентированность', + mission_point_2_text='Фокусируемся на потребностях и целях каждого клиента', + + mission_point_3_title='Непрерывное развитие', + mission_point_3_text='Постоянно совершенствуем наши навыки и знания', + + vision_badge='🔮 Наше видение', + vision_title='Будущее начинается сегодня', + vision_description='Мы стремимся стать ведущей IT-компанией в Корее, известной своими инновационными решениями, высоким качеством сервиса и способностью трансформировать бизнес-идеи в успешные цифровые продукты.', + + skill_1_name='Веб-разработка', + skill_1_percent=95, + + skill_2_name='Мобильная разработка', + skill_2_percent=90, + + skill_3_name='UI/UX Дизайн', + skill_3_percent=85, + + skill_4_name='DevOps', + skill_4_percent=80, + + team_badge='👥 Команда', + team_title='Познакомьтесь с нашей командой', + team_description='Талантливые профессионалы, которые воплощают ваши идеи в реальность', + + values_badge='💎 Наши ценности', + values_title='Что нами движет', + + value_1_icon='fa-lightbulb', + value_1_title='Инновации', + value_1_text='Мы постоянно ищем новые решения и подходы', + + value_2_icon='fa-handshake', + value_2_title='Партнерство', + value_2_text='Строим долгосрочные отношения с клиентами', + + value_3_icon='fa-chart-line', + value_3_title='Результат', + value_3_text='Фокусируемся на достижении целей клиента', + + value_4_icon='fa-shield-alt', + value_4_title='Надежность', + value_4_text='Гарантируем качество и безопасность', + + contact_title='Готовы начать проект?', + contact_description='Свяжитесь с нами сегодня, и мы поможем воплотить ваши идеи в жизнь', + + is_active=True + ) + self.stdout.write(self.style.SUCCESS('✅ AboutPage создана')) + else: + self.stdout.write(self.style.WARNING('⚠️ AboutPage уже существует')) + + # Создать Footer Settings + if not FooterSettings.objects.exists(): + FooterSettings.objects.create( + company_name='SmartSolTech', + company_description='Мы создаем инновационные IT-решения, которые помогают бизнесу расти и развиваться в цифровую эпоху.', + company_logo_icon='fa-code', + + telegram_url='https://t.me/smartsoltech', + instagram_url='https://instagram.com/smartsoltech', + linkedin_url='https://linkedin.com/company/smartsoltech', + github_url='https://github.com/smartsoltech', + + email='info@smartsoltech.kr', + phone='+82-10-XXXX-XXXX', + address='Seoul, South Korea', + + show_services_menu=True, + services_title='Услуги', + + show_company_menu=True, + company_menu_title='Компания', + + copyright_text='© 2025 SmartSolTech. Все права защищены.', + + is_active=True + ) + self.stdout.write(self.style.SUCCESS('✅ FooterSettings созданы')) + else: + self.stdout.write(self.style.WARNING('⚠️ FooterSettings уже существуют')) + + self.stdout.write(self.style.SUCCESS('\n✨ Готово! Данные созданы успешно')) diff --git a/smartsoltech/web/migrations/0010_aboutpage_footersettings.py b/smartsoltech/web/migrations/0010_aboutpage_footersettings.py new file mode 100644 index 0000000..580c9d4 --- /dev/null +++ b/smartsoltech/web/migrations/0010_aboutpage_footersettings.py @@ -0,0 +1,106 @@ +# Generated by Django 5.1.1 on 2025-11-24 00:13 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('web', '0009_alter_servicerequest_options_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='AboutPage', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('hero_badge', models.CharField(default='🚀 О нас', max_length=100, verbose_name='Hero Badge')), + ('hero_title', models.CharField(default='Мы создаем цифровое будущее', max_length=200, verbose_name='Заголовок Hero')), + ('hero_description', models.TextField(default='SmartSolTech - это команда профессионалов...', verbose_name='Описание Hero')), + ('stat_projects', models.IntegerField(default=50, verbose_name='Количество проектов')), + ('stat_clients', models.IntegerField(default=30, verbose_name='Количество клиентов')), + ('stat_years', models.IntegerField(default=3, verbose_name='Лет опыта')), + ('stat_support', models.CharField(default='24/7', max_length=50, verbose_name='Поддержка')), + ('mission_badge', models.CharField(default='🎯 Наша миссия', max_length=100, verbose_name='Mission Badge')), + ('mission_title', models.CharField(default='Делаем технологии доступными', max_length=200, verbose_name='Заголовок миссии')), + ('mission_description', models.TextField(verbose_name='Описание миссии')), + ('mission_point_1_title', models.CharField(default='Инновационные решения', max_length=200, verbose_name='Пункт миссии 1')), + ('mission_point_1_text', models.TextField(default='Используем передовые технологии...', verbose_name='Текст пункта 1')), + ('mission_point_2_title', models.CharField(default='Клиентоориентированность', max_length=200, verbose_name='Пункт миссии 2')), + ('mission_point_2_text', models.TextField(default='Фокусируемся на потребностях...', verbose_name='Текст пункта 2')), + ('mission_point_3_title', models.CharField(default='Непрерывное развитие', max_length=200, verbose_name='Пункт миссии 3')), + ('mission_point_3_text', models.TextField(default='Постоянно совершенствуем...', verbose_name='Текст пункта 3')), + ('vision_badge', models.CharField(default='🔮 Наше видение', max_length=100, verbose_name='Vision Badge')), + ('vision_title', models.CharField(default='Будущее начинается сегодня', max_length=200, verbose_name='Заголовок видения')), + ('vision_description', models.TextField(verbose_name='Описание видения')), + ('skill_1_name', models.CharField(default='Веб-разработка', max_length=100, verbose_name='Навык 1')), + ('skill_1_percent', models.IntegerField(default=95, verbose_name='Процент навыка 1')), + ('skill_2_name', models.CharField(default='Мобильная разработка', max_length=100, verbose_name='Навык 2')), + ('skill_2_percent', models.IntegerField(default=90, verbose_name='Процент навыка 2')), + ('skill_3_name', models.CharField(default='UI/UX Дизайн', max_length=100, verbose_name='Навык 3')), + ('skill_3_percent', models.IntegerField(default=85, verbose_name='Процент навыка 3')), + ('skill_4_name', models.CharField(default='DevOps', max_length=100, verbose_name='Навык 4')), + ('skill_4_percent', models.IntegerField(default=80, verbose_name='Процент навыка 4')), + ('team_badge', models.CharField(default='👥 Команда', max_length=100, verbose_name='Team Badge')), + ('team_title', models.CharField(default='Познакомьтесь с нашей командой', max_length=200, verbose_name='Заголовок команды')), + ('team_description', models.TextField(default='Талантливые профессионалы...', verbose_name='Описание команды')), + ('values_badge', models.CharField(default='💎 Наши ценности', max_length=100, verbose_name='Values Badge')), + ('values_title', models.CharField(default='Что нами движет', max_length=200, verbose_name='Заголовок ценностей')), + ('value_1_icon', models.CharField(default='fa-lightbulb', max_length=50, verbose_name='Иконка ценности 1')), + ('value_1_title', models.CharField(default='Инновации', max_length=100, verbose_name='Ценность 1')), + ('value_1_text', models.TextField(default='Мы постоянно ищем новые решения...', verbose_name='Текст ценности 1')), + ('value_2_icon', models.CharField(default='fa-handshake', max_length=50, verbose_name='Иконка ценности 2')), + ('value_2_title', models.CharField(default='Партнерство', max_length=100, verbose_name='Ценность 2')), + ('value_2_text', models.TextField(default='Строим долгосрочные отношения...', verbose_name='Текст ценности 2')), + ('value_3_icon', models.CharField(default='fa-chart-line', max_length=50, verbose_name='Иконка ценности 3')), + ('value_3_title', models.CharField(default='Результат', max_length=100, verbose_name='Ценность 3')), + ('value_3_text', models.TextField(default='Фокусируемся на достижении целей...', verbose_name='Текст ценности 3')), + ('value_4_icon', models.CharField(default='fa-shield-alt', max_length=50, verbose_name='Иконка ценности 4')), + ('value_4_title', models.CharField(default='Надежность', max_length=100, verbose_name='Ценность 4')), + ('value_4_text', models.TextField(default='Гарантируем качество и безопасность...', verbose_name='Текст ценности 4')), + ('contact_title', models.CharField(default='Готовы начать проект?', max_length=200, verbose_name='Заголовок контактов')), + ('contact_description', models.TextField(default='Свяжитесь с нами сегодня...', verbose_name='Описание контактов')), + ('is_active', models.BooleanField(default=True, verbose_name='Активна')), + ('updated_at', models.DateTimeField(auto_now=True, verbose_name='Обновлено')), + ], + options={ + 'verbose_name': 'Страница О нас', + 'verbose_name_plural': 'Страницы О нас', + }, + ), + migrations.CreateModel( + name='FooterSettings', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('company_name', models.CharField(default='SmartSolTech', max_length=100, verbose_name='Название компании')), + ('company_description', models.TextField(default='Мы создаем инновационные IT-решения, которые помогают бизнесу расти...', verbose_name='Описание компании')), + ('company_logo_icon', models.CharField(default='fa-code', max_length=50, verbose_name='Иконка компании')), + ('telegram_url', models.URLField(blank=True, verbose_name='Telegram URL')), + ('instagram_url', models.URLField(blank=True, verbose_name='Instagram URL')), + ('linkedin_url', models.URLField(blank=True, verbose_name='LinkedIn URL')), + ('github_url', models.URLField(blank=True, verbose_name='GitHub URL')), + ('facebook_url', models.URLField(blank=True, verbose_name='Facebook URL')), + ('twitter_url', models.URLField(blank=True, verbose_name='Twitter URL')), + ('email', models.EmailField(default='info@smartsoltech.kr', max_length=254, verbose_name='Email')), + ('phone', models.CharField(default='+82-10-XXXX-XXXX', max_length=50, verbose_name='Телефон')), + ('address', models.TextField(default='Seoul, South Korea', verbose_name='Адрес')), + ('show_services_menu', models.BooleanField(default=True, verbose_name='Показывать меню услуг')), + ('services_title', models.CharField(default='Услуги', max_length=100, verbose_name='Заголовок меню услуг')), + ('show_company_menu', models.BooleanField(default=True, verbose_name='Показывать меню компании')), + ('company_menu_title', models.CharField(default='Компания', max_length=100, verbose_name='Заголовок меню компании')), + ('copyright_text', models.CharField(default='© 2025 SmartSolTech. Все права защищены.', max_length=200, verbose_name='Текст Copyright')), + ('google_analytics', models.TextField(blank=True, help_text='Вставьте код Google Analytics (без тегов + + {% if footer_settings %} + {% if footer_settings.google_analytics %} + + {% endif %} + + {% if footer_settings.yandex_metrika %} + + {% endif %} + + {% if footer_settings.custom_head_scripts %} + {{ footer_settings.custom_head_scripts|safe }} + {% endif %} + {% endif %} + {% block extra_head %}{% endblock %} diff --git a/smartsoltech/web/views.py b/smartsoltech/web/views.py index c61d388..a33666d 100644 --- a/smartsoltech/web/views.py +++ b/smartsoltech/web/views.py @@ -1,5 +1,5 @@ from django.shortcuts import render, get_object_or_404, redirect -from .models import Service, Project, Client, BlogPost, Review, Order, ServiceRequest, Category +from .models import Service, Project, Client, BlogPost, Review, Order, ServiceRequest, Category, AboutPage, FooterSettings from django.db.models import Avg from comunication.models import TelegramSettings import qrcode @@ -87,7 +87,8 @@ def services_view(request): return render(request, 'web/services_modern.html', context) def about_view(request): - return render(request, 'web/about_modern.html') + about_page = AboutPage.objects.filter(is_active=True).first() + return render(request, 'web/about_modern.html', {'about': about_page}) def create_service_request(request, service_id): if request.method == 'POST':