"""
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 = 'Отключено типов'