""" Admin для упрощенной системы уведомлений """ from django.contrib import admin from django.utils.html import format_html from django.utils.safestring import mark_safe from .models import Notification, UserChannelPreferences @admin.register(Notification) class NotificationAdmin(admin.ModelAdmin): """Admin для модели Notification""" list_display = [ "id", "get_actor_display", "verb", "get_recipient_display", "unread", "public", "deleted", "emailed", "timestamp", ] list_filter = [ "unread", "public", "deleted", "emailed", "verb", "timestamp", ] search_fields = [ "recipient__username", "recipient__first_name", "recipient__last_name", "recipient__email", "verb", "description", ] readonly_fields = [ "get_actor_info", "get_action_object_info", "get_target_info", "timestamp", "timestamp_read", ] fieldsets = ( ( "Основная информация", { "fields": ( "recipient", "verb", "description", "action_url", ) }, ), ( "Связанные объекты", { "fields": ( "get_actor_info", "get_action_object_info", "get_target_info", ), "classes": ("collapse",), }, ), ( "Дополнительные данные", { "fields": ("data",), "classes": ("collapse",), }, ), ( "Статусы", { "fields": ( "unread", "timestamp_read", "public", "deleted", "emailed", ) }, ), ("Временные метки", {"fields": ("timestamp",)}), ) date_hierarchy = "timestamp" actions = [ "mark_as_read", "mark_as_unread", "mark_as_deleted", "mark_as_not_deleted", ] def get_actor_display(self, obj): """Отображение актора в списке""" if obj.actor: return format_html( '{}', obj.actor_content_type.model, str(obj.actor)[:50], ) return "-" get_actor_display.short_description = "Актор" def get_recipient_display(self, obj): """Отображение получателя""" return format_html( '{}', obj.recipient.id, obj.recipient.get_short_name(), ) get_recipient_display.short_description = "Получатель" def get_actor_info(self, obj): """Подробная информация об акторе""" if not obj.actor: return "-" info = f""" Тип: {obj.actor_content_type.model}
ID: {obj.actor_object_id}
Объект: {obj.actor} """ return mark_safe(info) get_actor_info.short_description = "Информация об акторе" def get_action_object_info(self, obj): """Подробная информация об объекте действия""" if not obj.action_object: return "-" info = f""" Тип: {obj.action_object_content_type.model}
ID: {obj.action_object_object_id}
Объект: {obj.action_object} """ return mark_safe(info) get_action_object_info.short_description = "Объект действия" def get_target_info(self, obj): """Подробная информация о целевом объекте""" if not obj.target: return "-" info = f""" Тип: {obj.target_content_type.model}
ID: {obj.target_object_id}
Объект: {obj.target} """ return mark_safe(info) get_target_info.short_description = "Целевой объект" # === Actions === @admin.action(description="Отметить как прочитанные") def mark_as_read(self, request, queryset): """Отметить выбранные уведомления как прочитанные""" count = 0 for notification in queryset: if notification.unread: notification.mark_as_read() count += 1 self.message_user( request, f"Отмечено как прочитанные: {count} уведомлений" ) @admin.action(description="Отметить как непрочитанные") def mark_as_unread(self, request, queryset): """Отметить выбранные уведомления как непрочитанные""" count = 0 for notification in queryset: if not notification.unread: notification.mark_as_unread() count += 1 self.message_user( request, f"Отмечено как непрочитанные: {count} уведомлений" ) @admin.action(description="Пометить как удаленные") def mark_as_deleted(self, request, queryset): """Пометить как удаленные (мягкое удаление)""" count = queryset.filter(deleted=False).update(deleted=True) self.message_user( request, f"Помечено как удаленные: {count} уведомлений" ) @admin.action(description="Восстановить удаленные") def mark_as_not_deleted(self, request, queryset): """Восстановить удаленные""" count = queryset.filter(deleted=True).update(deleted=False) self.message_user(request, f"Восстановлено: {count} уведомлений") @admin.register(UserChannelPreferences) class UserChannelPreferencesAdmin(admin.ModelAdmin): """Admin для настроек каналов пользователя""" list_display = [ "user", "web_enabled", "email_enabled", "push_enabled", "email_frequency", "dnd_enabled", "get_disabled_verbs_count", ] list_filter = [ "web_enabled", "email_enabled", "push_enabled", "email_frequency", "dnd_enabled", ] search_fields = [ "user__username", "user__first_name", "user__last_name", "user__email", ] fieldsets = ( ("Пользователь", {"fields": ("user",)}), ( "Каналы доставки", { "fields": ( "web_enabled", "email_enabled", "push_enabled", ) }, ), ("Email настройки", {"fields": ("email_frequency",)}), ( 'Режим "Не беспокоить"', { "fields": ( "dnd_enabled", "dnd_start_time", "dnd_end_time", ) }, ), ( "Фильтры", { "fields": ("disabled_verbs",), "classes": ("collapse",), }, ), ) readonly_fields = [] def get_disabled_verbs_count(self, obj): """Количество отключенных типов""" count = len(obj.disabled_verbs) if count == 0: return "-" return format_html( '{} типов', ", ".join(obj.disabled_verbs), count, ) get_disabled_verbs_count.short_description = "Отключено типов"