from django.contrib import admin from django.utils.translation import gettext_lazy as _ from unfold.admin import ModelAdmin, StackedInline, TabularInline from unfold.decorators import display, action from apps.cms.models.post import ( PostCategory, PostTag, Post, PostComment, PostLike, MediaAsset, ) from utils.admin import project_admin_site class PostCommentInline(TabularInline): model = PostComment extra = 0 fields = ('author_name', 'author_email', 'user', 'content', 'status', 'created_at') readonly_fields = ('created_at',) @admin.register(Post, site=project_admin_site) class PostAdmin(ModelAdmin): list_display = ( 'title', 'post_type_badge', 'language', 'category', 'status_badge', 'author', 'views_count', 'likes_count', 'is_featured', 'publish_date', ) list_filter = ('post_type', 'language', 'status', 'is_featured', 'category') search_fields = ('title', 'excerpt', 'content', 'author__email', 'author__fullname') prepopulated_fields = {'slug': ('title',)} readonly_fields = ('reading_time_minutes', 'views_count', 'likes_count', 'created_at', 'updated_at') inlines = [PostCommentInline] actions = ['publish_posts', 'archive_posts', 'toggle_featured'] fieldsets = ( (_('Article Content'), { 'fields': ('title', 'slug', 'post_type', 'category', 'language', 'status', 'is_featured') }), (_('Author & Affiliation'), { 'fields': ('author', 'institution', 'author_role_label', 'author_custom_avatar') }), (_('Media & Excerpt'), { 'fields': ('featured_image', 'excerpt', 'content', 'tags') }), (_('Metrics & Scheduling'), { 'fields': ('reading_time_minutes', 'views_count', 'likes_count', 'publish_date', 'created_at', 'updated_at') }), ) @display(description=_('Type')) def post_type_badge(self, obj): return obj.get_post_type_display() @display(description=_('Status'), label={ Post.Status.PUBLISHED: "success", Post.Status.REVIEW: "warning", Post.Status.DRAFT: "info", Post.Status.ARCHIVED: "danger", }) def status_badge(self, obj): return obj.get_status_display() @action(description=_('Publish selected posts')) def publish_posts(self, request, queryset): count = queryset.update(status=Post.Status.PUBLISHED) self.message_user(request, _(f"{count} post(s) published successfully.")) @action(description=_('Archive selected posts')) def archive_posts(self, request, queryset): count = queryset.update(status=Post.Status.ARCHIVED) self.message_user(request, _(f"{count} post(s) archived.")) @action(description=_('Toggle featured status for selected posts')) def toggle_featured(self, request, queryset): for item in queryset: item.is_featured = not item.is_featured item.save(update_fields=['is_featured']) self.message_user(request, _("Featured status updated.")) @admin.register(PostCategory, site=project_admin_site) class PostCategoryAdmin(ModelAdmin): list_display = ('name', 'slug', 'language', 'created_at') list_filter = ('language',) search_fields = ('name', 'description') prepopulated_fields = {'slug': ('name',)} @admin.register(PostTag, site=project_admin_site) class PostTagAdmin(ModelAdmin): list_display = ('name', 'slug') search_fields = ('name',) prepopulated_fields = {'slug': ('name',)} @admin.register(PostComment, site=project_admin_site) class PostCommentAdmin(ModelAdmin): list_display = ('author_display', 'post', 'status_badge', 'created_at') list_filter = ('status', 'created_at') search_fields = ('author_name', 'author_email', 'content', 'post__title') actions = ['approve_comments', 'mark_as_spam'] @display(description=_('Author')) def author_display(self, obj): return obj.author_name or (obj.user.fullname if obj.user else "Anonymous") @display(description=_('Status'), label={ PostComment.Status.APPROVED: "success", PostComment.Status.PENDING: "warning", PostComment.Status.SPAM: "danger", }) def status_badge(self, obj): return obj.get_status_display() @action(description=_('Approve selected comments')) def approve_comments(self, request, queryset): count = queryset.update(status=PostComment.Status.APPROVED) self.message_user(request, _(f"{count} comment(s) approved.")) @action(description=_('Mark selected comments as spam')) def mark_as_spam(self, request, queryset): count = queryset.update(status=PostComment.Status.SPAM) self.message_user(request, _(f"{count} comment(s) marked as spam.")) @admin.register(PostLike, site=project_admin_site) class PostLikeAdmin(ModelAdmin): list_display = ('user', 'post', 'created_at') search_fields = ('user__email', 'user__fullname', 'post__title') readonly_fields = ('created_at',) @admin.register(MediaAsset, site=project_admin_site) class MediaAssetAdmin(ModelAdmin): list_display = ('title', 'media_type', 'file_size', 'uploaded_by', 'created_at') list_filter = ('media_type', 'created_at') search_fields = ('title', 'uploaded_by__email') readonly_fields = ('created_at',)