from django.contrib import admin from .models import Category, Article, Comment from django.db import models from django_ckeditor_5.widgets import CKEditor5Widget from django.utils.html import format_html from django.urls import reverse from programmer.tasks import send_new_article_notification from django.contrib import messages @admin.register(Category) class CategoryAdmin(admin.ModelAdmin): list_display = ('name', 'slug', 'description') prepopulated_fields = {'slug': ('name',)} search_fields = ('name',) @admin.register(Article) class ArticleAdmin(admin.ModelAdmin): formfield_overrides = { models.TextField: {'widget': CKEditor5Widget(config_name='default')}, } list_display = ('title', 'category', 'author', 'is_published', 'views_count', 'time_create', 'tag_list') list_filter = ('is_published', 'category', 'tags', 'time_create') search_fields = ('title', 'content', 'tags__name') prepopulated_fields = {'slug': ('title',)} autocomplete_fields = ('author',) # вместо raw_id_fields для удобства # filter_horizontal = ('tags',) # для удобного выбора тегов raw_id_fields = ('author',) # удобно при большом количестве пользователей date_hierarchy = 'time_create' actions = ['make_published', 'make_unpublished', 'send_notification'] fieldsets = ( (None, { 'fields': ('title', 'slug', 'category', 'author', 'tags', 'is_published') }), ('Содержание', { 'fields': ('content', 'image'), 'description': 'Основной текст статьи. Используйте редактор для форматирования.' }), ('SEO', { 'fields': ('meta_description',), 'classes': ('collapse',), }), ('Служебное', { 'fields': ('views_count',), 'classes': ('collapse',), }), ) readonly_fields = ('views_count',) # только для просмотра def get_queryset(self, request): return super().get_queryset(request).prefetch_related('tags') def tag_list(self, obj): return ", ".join(o.name for o in obj.tags.all()) tag_list.short_description = "Теги" def make_published(self, request, queryset): queryset.update(is_published=True) make_published.short_description = "Опубликовать выбранные статьи" def make_unpublished(self, request, queryset): queryset.update(is_published=False) make_unpublished.short_description = "Снять с публикации" def send_notification(self, request, queryset): """Отправить уведомления подписчикам для выбранных статей.""" published = queryset.filter(is_published=True) count = published.count() if count == 0: self.message_user(request, "Нет опубликованных статей для отправки уведомлений.", level=messages.WARNING) return for article in published: send_new_article_notification.delay(article.id) self.message_user(request, f"Уведомления отправлены для {count} статей.") send_notification.short_description = "Отправить уведомление подписчикам о новых статьях" # Добавляем кнопку предпросмотра для черновиков def view_on_site(self, obj): if obj.is_published: return obj.get_absolute_url() else: # ссылка на предпросмотр черновика return reverse('blog:draft_preview', args=[obj.slug]) view_on_site.short_description = "Предпросмотр" @admin.register(Comment) class CommentAdmin(admin.ModelAdmin): list_display = ('author_name', 'article', 'parent', 'is_moderated', 'time_create') list_filter = ('is_moderated', 'time_create', 'parent') search_fields = ('author_name', 'author_email', 'content', 'parent__author_name') actions = ['approve_comments', 'reject_comments'] fields = ('article', 'author_name', 'author_email', 'user', 'parent', 'content', 'is_moderated', 'time_create') readonly_fields = ('time_create',) def approve_comments(self, request, queryset): queryset.update(is_moderated=True) approve_comments.short_description = "Одобрить выбранные комментарии" def reject_comments(self, request, queryset): queryset.update(is_moderated=False) reject_comments.short_description = "Отклонить выбранные комментарии"