feat: добавлены модели AboutPage и FooterSettings с админ-панелью и интеграцией скриптов

This commit is contained in:
2025-11-24 09:18:22 +09:00
parent ee3a1bf846
commit 3cea013a8e
9 changed files with 558 additions and 17 deletions

View File

@@ -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
],
},
},

View File

@@ -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)
@@ -46,3 +49,104 @@ class ServiceRequestAdmin(admin.ModelAdmin):
list_display = ('service','token', 'client', 'created_at')
search_fields = ('service','token', 'client')
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': 'Вставьте коды аналитики без тегов <script></script>',
'classes': ('collapse',)
}),
('Дополнительные скрипты', {
'fields': ('custom_head_scripts', 'custom_body_scripts'),
'description': 'Вставьте дополнительные скрипты С тегами <script></script>',
'classes': ('collapse',)
}),
('Настройки', {
'fields': ('is_active',)
}),
)
def has_add_permission(self, request):
return not FooterSettings.objects.filter(is_active=True).exists()

View File

@@ -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
}

View File

@@ -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='Мы создаем <span class="text-gradient">цифровое будущее</span>',
hero_description='SmartSolTech - это команда профессионалов, которые превращают идеи в инновационные IT-решения. Мы помогаем бизнесу расти и развиваться в цифровую эпоху.',
stat_projects=50,
stat_clients=30,
stat_years=3,
stat_support='24/7',
mission_badge='🎯 Наша миссия',
mission_title='Делаем технологии <span class="text-gradient">доступными</span>',
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='Будущее начинается <span class="text-gradient">сегодня</span>',
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='Познакомьтесь с <span class="text-gradient">нашей командой</span>',
team_description='Талантливые профессионалы, которые воплощают ваши идеи в реальность',
values_badge='💎 Наши ценности',
values_title='Что нами <span class="text-gradient">движет</span>',
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✨ Готово! Данные созданы успешно'))

View File

@@ -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 (без тегов <script>)', verbose_name='Google Analytics')),
('google_adsense', models.TextField(blank=True, help_text='Вставьте код Google AdSense (без тегов <script>)', verbose_name='Google AdSense')),
('yandex_metrika', models.TextField(blank=True, help_text='Вставьте код Яндекс Метрики (без тегов <script>)', verbose_name='Яндекс Метрика')),
('facebook_pixel', models.TextField(blank=True, help_text='Вставьте код Facebook Pixel (без тегов <script>)', verbose_name='Facebook Pixel')),
('custom_head_scripts', models.TextField(blank=True, help_text='Дополнительные скрипты для вставки в <head> (с тегами <script>)', verbose_name='Скрипты в <head>')),
('custom_body_scripts', models.TextField(blank=True, help_text='Дополнительные скрипты для вставки перед закрывающим </body> (с тегами <script>)', verbose_name='Скрипты перед </body>')),
('is_active', models.BooleanField(default=True, verbose_name='Активно')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Обновлено')),
],
options={
'verbose_name': 'Настройки футера',
'verbose_name_plural': 'Настройки футера',
},
),
]

View File

@@ -153,3 +153,191 @@ class Review(models.Model):
def __str__(self):
return f"Отзыв от {self.client.first_name} {self.client.last_name} for {self.service.name}"
class AboutPage(models.Model):
"""Модель для страницы 'О нас' - все данные управляются из админки"""
# Hero Section
hero_badge = models.CharField(max_length=100, default='🚀 О нас', verbose_name='Hero Badge')
hero_title = models.CharField(max_length=200, default='Мы создаем цифровое будущее', verbose_name='Заголовок Hero')
hero_description = models.TextField(default='SmartSolTech - это команда профессионалов...', verbose_name='Описание Hero')
# Statistics
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(max_length=50, default='24/7', verbose_name='Поддержка')
# Mission Section
mission_badge = models.CharField(max_length=100, default='🎯 Наша миссия', verbose_name='Mission Badge')
mission_title = models.CharField(max_length=200, default='Делаем технологии доступными', verbose_name='Заголовок миссии')
mission_description = models.TextField(verbose_name='Описание миссии')
mission_point_1_title = models.CharField(max_length=200, default='Инновационные решения', verbose_name='Пункт миссии 1')
mission_point_1_text = models.TextField(default='Используем передовые технологии...', verbose_name='Текст пункта 1')
mission_point_2_title = models.CharField(max_length=200, default='Клиентоориентированность', verbose_name='Пункт миссии 2')
mission_point_2_text = models.TextField(default='Фокусируемся на потребностях...', verbose_name='Текст пункта 2')
mission_point_3_title = models.CharField(max_length=200, default='Непрерывное развитие', verbose_name='Пункт миссии 3')
mission_point_3_text = models.TextField(default='Постоянно совершенствуем...', verbose_name='Текст пункта 3')
# Vision Section
vision_badge = models.CharField(max_length=100, default='🔮 Наше видение', verbose_name='Vision Badge')
vision_title = models.CharField(max_length=200, default='Будущее начинается сегодня', verbose_name='Заголовок видения')
vision_description = models.TextField(verbose_name='Описание видения')
# Skills
skill_1_name = models.CharField(max_length=100, default='Веб-разработка', verbose_name='Навык 1')
skill_1_percent = models.IntegerField(default=95, verbose_name='Процент навыка 1')
skill_2_name = models.CharField(max_length=100, default='Мобильная разработка', verbose_name='Навык 2')
skill_2_percent = models.IntegerField(default=90, verbose_name='Процент навыка 2')
skill_3_name = models.CharField(max_length=100, default='UI/UX Дизайн', verbose_name='Навык 3')
skill_3_percent = models.IntegerField(default=85, verbose_name='Процент навыка 3')
skill_4_name = models.CharField(max_length=100, default='DevOps', verbose_name='Навык 4')
skill_4_percent = models.IntegerField(default=80, verbose_name='Процент навыка 4')
# Team Section
team_badge = models.CharField(max_length=100, default='👥 Команда', verbose_name='Team Badge')
team_title = models.CharField(max_length=200, default='Познакомьтесь с нашей командой', verbose_name='Заголовок команды')
team_description = models.TextField(default='Талантливые профессионалы...', verbose_name='Описание команды')
# Values Section
values_badge = models.CharField(max_length=100, default='💎 Наши ценности', verbose_name='Values Badge')
values_title = models.CharField(max_length=200, default='Что нами движет', verbose_name='Заголовок ценностей')
value_1_icon = models.CharField(max_length=50, default='fa-lightbulb', verbose_name='Иконка ценности 1')
value_1_title = models.CharField(max_length=100, default='Инновации', verbose_name='Ценность 1')
value_1_text = models.TextField(default='Мы постоянно ищем новые решения...', verbose_name='Текст ценности 1')
value_2_icon = models.CharField(max_length=50, default='fa-handshake', verbose_name='Иконка ценности 2')
value_2_title = models.CharField(max_length=100, default='Партнерство', verbose_name='Ценность 2')
value_2_text = models.TextField(default='Строим долгосрочные отношения...', verbose_name='Текст ценности 2')
value_3_icon = models.CharField(max_length=50, default='fa-chart-line', verbose_name='Иконка ценности 3')
value_3_title = models.CharField(max_length=100, default='Результат', verbose_name='Ценность 3')
value_3_text = models.TextField(default='Фокусируемся на достижении целей...', verbose_name='Текст ценности 3')
value_4_icon = models.CharField(max_length=50, default='fa-shield-alt', verbose_name='Иконка ценности 4')
value_4_title = models.CharField(max_length=100, default='Надежность', verbose_name='Ценность 4')
value_4_text = models.TextField(default='Гарантируем качество и безопасность...', verbose_name='Текст ценности 4')
# Contact Section
contact_title = models.CharField(max_length=200, default='Готовы начать проект?', verbose_name='Заголовок контактов')
contact_description = models.TextField(default='Свяжитесь с нами сегодня...', verbose_name='Описание контактов')
# Meta
is_active = models.BooleanField(default=True, verbose_name='Активна')
updated_at = models.DateTimeField(auto_now=True, verbose_name='Обновлено')
class Meta:
verbose_name = 'Страница О нас'
verbose_name_plural = 'Страницы О нас'
def __str__(self):
return f"О нас (обновлено: {self.updated_at.strftime('%d.%m.%Y')})"
def save(self, *args, **kwargs):
# Оставляем только одну активную запись
if self.is_active:
AboutPage.objects.exclude(pk=self.pk).update(is_active=False)
super().save(*args, **kwargs)
class FooterSettings(models.Model):
"""Настройки футера - все данные управляются из админки"""
# Company Info
company_name = models.CharField(max_length=100, default='SmartSolTech', verbose_name='Название компании')
company_description = models.TextField(
default='Мы создаем инновационные IT-решения, которые помогают бизнесу расти...',
verbose_name='Описание компании'
)
company_logo_icon = models.CharField(max_length=50, default='fa-code', verbose_name='Иконка компании')
# Social Links
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')
# Contact Info
email = models.EmailField(default='info@smartsoltech.kr', verbose_name='Email')
phone = models.CharField(max_length=50, default='+82-10-XXXX-XXXX', verbose_name='Телефон')
address = models.TextField(default='Seoul, South Korea', verbose_name='Адрес')
# Services Links (for footer menu)
show_services_menu = models.BooleanField(default=True, verbose_name='Показывать меню услуг')
services_title = models.CharField(max_length=100, default='Услуги', verbose_name='Заголовок меню услуг')
# Company Links (for footer menu)
show_company_menu = models.BooleanField(default=True, verbose_name='Показывать меню компании')
company_menu_title = models.CharField(max_length=100, default='Компания', verbose_name='Заголовок меню компании')
# Copyright
copyright_text = models.CharField(
max_length=200,
default='© 2025 SmartSolTech. Все права защищены.',
verbose_name='Текст Copyright'
)
# Integration Scripts
google_analytics = models.TextField(
blank=True,
verbose_name='Google Analytics',
help_text='Вставьте код Google Analytics (без тегов <script>)'
)
google_adsense = models.TextField(
blank=True,
verbose_name='Google AdSense',
help_text='Вставьте код Google AdSense (без тегов <script>)'
)
yandex_metrika = models.TextField(
blank=True,
verbose_name='Яндекс Метрика',
help_text='Вставьте код Яндекс Метрики (без тегов <script>)'
)
facebook_pixel = models.TextField(
blank=True,
verbose_name='Facebook Pixel',
help_text='Вставьте код Facebook Pixel (без тегов <script>)'
)
custom_head_scripts = models.TextField(
blank=True,
verbose_name='Скрипты в <head>',
help_text='Дополнительные скрипты для вставки в <head> (с тегами <script>)'
)
custom_body_scripts = models.TextField(
blank=True,
verbose_name='Скрипты перед </body>',
help_text='Дополнительные скрипты для вставки перед закрывающим </body> (с тегами <script>)'
)
# Meta
is_active = models.BooleanField(default=True, verbose_name='Активно')
updated_at = models.DateTimeField(auto_now=True, verbose_name='Обновлено')
class Meta:
verbose_name = 'Настройки футера'
verbose_name_plural = 'Настройки футера'
def __str__(self):
return f"Футер (обновлено: {self.updated_at.strftime('%d.%m.%Y')})"
def save(self, *args, **kwargs):
# Оставляем только одну активную запись
if self.is_active:
FooterSettings.objects.exclude(pk=self.pk).update(is_active=False)
super().save(*args, **kwargs)

View File

@@ -9,14 +9,13 @@
<div class="row align-items-center">
<div class="col-lg-6">
<span class="badge bg-gradient text-white mb-3 px-3 py-2 rounded-pill">
🚀 О нас
{{ about.hero_badge|default:"🚀 О нас" }}
</span>
<h1 class="display-4 fw-bold mb-4">
Мы создаем <span class="text-gradient">цифровое будущее</span>
{{ about.hero_title|default:"Мы создаем цифровое будущее"|safe }}
</h1>
<p class="lead text-muted mb-4">
SmartSolTech - это команда профессионалов, которые превращают идеи в инновационные IT-решения.
Мы помогаем бизнесу расти и развиваться в цифровую эпоху.
{{ about.hero_description|default:"SmartSolTech - это команда профессионалов..." }}
</p>
<div class="d-flex flex-wrap gap-3">
<a href="#team" class="btn btn-primary-modern">
@@ -40,7 +39,7 @@
<div class="stat-icon bg-primary rounded-3 mb-3 mx-auto" style="width: 60px; height: 60px; display: flex; align-items: center; justify-content: center;">
<i class="fas fa-code text-white fa-2x"></i>
</div>
<h3 class="text-gradient fw-bold">50+</h3>
<h3 class="text-gradient fw-bold">{{ about.stat_projects|default:"50" }}+</h3>
<p class="mb-0 text-muted">Проектов</p>
</div>
</div>
@@ -49,7 +48,7 @@
<div class="stat-icon bg-success rounded-3 mb-3 mx-auto" style="width: 60px; height: 60px; display: flex; align-items: center; justify-content: center;">
<i class="fas fa-users text-white fa-2x"></i>
</div>
<h3 class="text-gradient fw-bold">30+</h3>
<h3 class="text-gradient fw-bold">{{ about.stat_clients|default:"30" }}+</h3>
<p class="mb-0 text-muted">Клиентов</p>
</div>
</div>
@@ -58,7 +57,7 @@
<div class="stat-icon bg-warning rounded-3 mb-3 mx-auto" style="width: 60px; height: 60px; display: flex; align-items: center; justify-content: center;">
<i class="fas fa-award text-white fa-2x"></i>
</div>
<h3 class="text-gradient fw-bold">3+</h3>
<h3 class="text-gradient fw-bold">{{ about.stat_years|default:"3" }}+</h3>
<p class="mb-0 text-muted">Лет опыта</p>
</div>
</div>
@@ -67,7 +66,7 @@
<div class="stat-icon bg-info rounded-3 mb-3 mx-auto" style="width: 60px; height: 60px; display: flex; align-items: center; justify-content: center;">
<i class="fas fa-rocket text-white fa-2x"></i>
</div>
<h3 class="text-gradient fw-bold">24/7</h3>
<h3 class="text-gradient fw-bold">{{ about.stat_support|default:"24/7" }}</h3>
<p class="mb-0 text-muted">Поддержка</p>
</div>
</div>
@@ -87,15 +86,13 @@
<div class="col-lg-6">
<div class="pe-lg-4">
<span class="badge bg-primary text-white mb-3 px-3 py-2 rounded-pill">
🎯 Наша миссия
{{ about.mission_badge|default:"🎯 Наша миссия" }}
</span>
<h2 class="display-6 fw-bold mb-4">
Делаем технологии <span class="text-gradient">доступными</span>
{{ about.mission_title|default:"Делаем технологии доступными"|safe }}
</h2>
<p class="text-muted mb-4">
Мы верим, что каждый бизнес заслуживает доступа к современным технологиям.
Наша миссия — демократизировать IT-решения и помочь компаниям любого размера
достичь цифрового совершенства.
{{ about.mission_description|default:"Мы верим, что каждый бизнес заслуживает..." }}
</p>
<div class="mission-points">
<div class="d-flex align-items-start mb-3">

View File

@@ -36,6 +36,25 @@
<!-- Force unblock script - загружается ПЕРВЫМ для предотвращения блокировки -->
<script src="{% static 'assets/js/force-unblock.js' %}"></script>
<!-- Integration Scripts from Footer Settings -->
{% if footer_settings %}
{% if footer_settings.google_analytics %}
<script>
{{ footer_settings.google_analytics|safe }}
</script>
{% endif %}
{% if footer_settings.yandex_metrika %}
<script>
{{ footer_settings.yandex_metrika|safe }}
</script>
{% endif %}
{% if footer_settings.custom_head_scripts %}
{{ footer_settings.custom_head_scripts|safe }}
{% endif %}
{% endif %}
{% block extra_head %}{% endblock %}
</head>
<body>

View File

@@ -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':