from django.contrib import admin from .models import ( Service, Project, Client, Order, Review, BlogPost, Category, ServiceRequest, AboutPage, FooterSettings, TeamMember, PortfolioItem, PrivacyPolicy, TermsOfUse, NewsArticle, CareerVacancy, SiteSettings, PortfolioImage, ContactSettings ) from .forms import ProjectForm @admin.register(Service) class ServiceAdmin(admin.ModelAdmin): list_display = ('name', 'category', 'price') search_fields = ('name', 'category') @admin.register(Project) class ProjectAdmin(admin.ModelAdmin): form = ProjectForm list_display = ('name', 'client','service', 'status', 'order', 'description') list_filter = ('name', 'client','service', 'status', 'order') search_fields = ('name', 'client','service', 'status', 'order', 'client__first_name', 'client__last_name') @admin.register(Client) class ClientAdmin(admin.ModelAdmin): list_display = ('first_name', 'last_name', 'email', 'phone_number') search_fields = ('first_name', 'last_name', 'email') @admin.register(Order) class OrderAdmin(admin.ModelAdmin): list_display = ('id', 'service', 'client', 'client__email', 'client__phone_number', 'status') list_filter = ('status','client', 'order_date') search_fields = ('client__first_name', 'service__name','status','client', 'order_date') @admin.register(Review) class ReviewAdmin(admin.ModelAdmin): list_display = ('client', 'service', 'rating', 'review_date') list_filter = ('rating',) search_fields = ('client__first_name', 'service__name') @admin.register(BlogPost) class BlogPostAdmin(admin.ModelAdmin): list_display = ('title', 'status', 'author', 'published_date') list_filter = ('status', 'published_date') search_fields = ('title', 'excerpt', 'author__username') prepopulated_fields = {'slug': ('title',)} @admin.register(Category) class CategoryAdmin(admin.ModelAdmin): list_display = ('name','description') search_fields = ('name',) class PortfolioImageInline(admin.TabularInline): model = PortfolioImage extra = 3 fields = ('image', 'caption', 'order') verbose_name = 'Дополнительное изображение' verbose_name_plural = 'Галерея изображений' @admin.register(PortfolioItem) class PortfolioItemAdmin(admin.ModelAdmin): list_display = ('title', 'client_name', 'completion_date', 'featured', 'is_active', 'gallery_count', 'categories_display') list_filter = ('featured', 'is_active', 'completion_date', 'categories') search_fields = ('title', 'client_name', 'description') prepopulated_fields = {'slug': ('title',)} filter_horizontal = ('categories',) inlines = [PortfolioImageInline] def gallery_count(self, obj): return obj.gallery_images.count() gallery_count.short_description = 'Фото в галерее' # type: ignore def categories_display(self, obj): return ", ".join([cat.name for cat in obj.categories.all()[:3]]) categories_display.short_description = 'Категории' # type: ignore @admin.register(NewsArticle) class NewsArticleAdmin(admin.ModelAdmin): list_display = ('title', 'is_published', 'published_date', 'created_at') list_filter = ('is_published', 'published_date', 'created_at') search_fields = ('title', 'excerpt') prepopulated_fields = {'slug': ('title',)} @admin.register(CareerVacancy) class CareerVacancyAdmin(admin.ModelAdmin): list_display = ('title', 'location', 'employment_type', 'is_active', 'posted_at') list_filter = ('employment_type', 'is_active', 'posted_at') search_fields = ('title', 'location') prepopulated_fields = {'slug': ('title',)} @admin.register(PrivacyPolicy) class PrivacyPolicyAdmin(admin.ModelAdmin): list_display = ('version', 'effective_date', 'is_active') list_filter = ('is_active', 'effective_date') search_fields = ('version',) @admin.register(TermsOfUse) class TermsOfUseAdmin(admin.ModelAdmin): list_display = ('version', 'effective_date', 'is_active') list_filter = ('is_active', 'effective_date') search_fields = ('version',) @admin.register(ServiceRequest) 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 AboutPage.objects.count() == 0 def has_delete_permission(self, request, obj=None): # Запретить удаление return False @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 FooterSettings.objects.count() == 0 def has_delete_permission(self, request, obj=None): # Запретить удаление единственной активной записи return False @admin.register(TeamMember) class TeamMemberAdmin(admin.ModelAdmin): list_display = ('full_name', 'position', 'order', 'is_active', 'email', 'updated_at') list_filter = ('is_active', 'position') search_fields = ('first_name', 'last_name', 'position', 'email') list_editable = ('order', 'is_active') fieldsets = ( ('Основная информация', { 'fields': ('first_name', 'last_name', 'position', 'photo') }), ('О специалисте', { 'fields': ('bio', 'specialization') }), ('Контакты', { 'fields': ('email', 'phone', 'telegram', 'linkedin', 'github'), 'classes': ('collapse',) }), ('Настройки отображения', { 'fields': ('order', 'is_active') }), ) def full_name(self, obj): return obj.full_name full_name.short_description = 'ФИО' # type: ignore full_name.admin_order_field = 'last_name' # type: ignore @admin.register(SiteSettings) class SiteSettingsAdmin(admin.ModelAdmin): list_display = ('currency_symbol',) fieldsets = ( ('Настройки валюты', { 'fields': ('currency_symbol',) }), ) def has_add_permission(self, request): # Запретить создание новых записей (singleton) return not SiteSettings.objects.exists() def has_delete_permission(self, request, obj=None): # Запретить удаление настроек return False @admin.register(ContactSettings) class ContactSettingsAdmin(admin.ModelAdmin): list_display = ('company_name', 'email', 'phone', 'telegram', 'updated_at') fieldsets = ( ('📋 Основная информация', { 'fields': ('company_name',), 'description': 'Название компании' }), ('📞 Основные контакты', { 'fields': ('email', 'phone', 'telegram', 'whatsapp'), 'description': 'Главные каналы связи с клиентами' }), ('📍 Адрес и режим работы', { 'fields': ('address', 'working_hours'), }), ('🌐 Социальные сети', { 'fields': ( 'telegram_url', 'instagram_url', 'linkedin_url', 'facebook_url', 'twitter_url', 'youtube_url', 'github_url' ), 'classes': ('collapse',), 'description': 'Ссылки на страницы в социальных сетях' }), ('📧 Дополнительные контакты', { 'fields': ('support_email', 'sales_email', 'emergency_phone'), 'classes': ('collapse',), 'description': 'Специализированные контакты (опционально)' }), ) def has_add_permission(self, request): # Запретить создание новых записей (singleton) return not ContactSettings.objects.exists() def has_delete_permission(self, request, obj=None): # Запретить удаление контактов return False class Media: css = { 'all': ('admin/css/forms.css',) }