# posts/admin.py from django.contrib import admin from .models import TgChat, PostTemplate, MediaItem, Post, PostJob from django.utils.html import format_html from django.utils import timezone from .utils import render_post_text, build_keyboard, send_post_to_chat @admin.register(TgChat) class TgChatAdmin(admin.ModelAdmin): list_display = ("chat_id", "title", "username", "type", "is_active", "added_at") list_filter = ("type", "is_active") search_fields = ("chat_id", "title", "username") @admin.register(PostTemplate) class PostTemplateAdmin(admin.ModelAdmin): list_display = ("name", "parse_mode") search_fields = ("name", "text") @admin.register(MediaItem) class MediaItemAdmin(admin.ModelAdmin): list_display = ("type", "file_id", "local_path", "order") list_filter = ("type",) search_fields = ("file_id", "local_path") class MediaInline(admin.TabularInline): model = Post.media.through extra = 0 verbose_name = "Медиа" verbose_name_plural = "Медиа" @admin.action(description="Опубликовать выбранные посты сейчас") def publish_now(modeladmin, request, queryset): for post in queryset: for chat in post.target_chats.all(): try: text = render_post_text(post) kb = build_keyboard(post.buttons) send_post_to_chat(chat.chat_id, post, text, kb) except Exception as e: post.status = Post.FAILED post.save(update_fields=["status"]) modeladmin.message_user(request, f"Ошибка публикации поста {post.id} в чат {chat}: {e}", level="error") post.status = Post.SENT post.save(update_fields=["status"]) @admin.register(Post) class PostAdmin(admin.ModelAdmin): list_display = ("id", "title", "status", "scheduled_at", "created_at", "updated_at", "preview_text") list_filter = ("status", "scheduled_at", "created_at") search_fields = ("title", "text") inlines = [MediaInline] actions = [publish_now] filter_horizontal = ("target_chats",) def preview_text(self, obj): return format_html("
{}
", (obj.text or "")[:200]) preview_text.short_description = "Текст (превью)" @admin.register(PostJob) class PostJobAdmin(admin.ModelAdmin): list_display = ("id", "post", "chat", "run_at", "status", "attempts", "max_attempts", "last_error_short") list_filter = ("status", "run_at") search_fields = ("post__title", "chat__title", "last_error") def last_error_short(self, obj): return (obj.last_error or "")[:100] last_error_short.short_description = "Последняя ошибка"