feat(blog): expand publishing and moderation APIs
This commit is contained in:
@@ -4,22 +4,22 @@ from django.contrib import admin
|
||||
from import_export.admin import ImportExportModelAdmin
|
||||
from simplemde.widgets import SimpleMDEEditor
|
||||
|
||||
from apps.blog.models import Category, Tag, Post, PostAsset, Comment, Like, SavedPost
|
||||
from apps.blog.models import BlogBanner, Category, Tag, Post, PostAsset, Comment, Like, SavedPost
|
||||
from apps.blog.resources import PostResource, CategoryResource
|
||||
from core.admin import SoftDeleteListFilter, BaseModelAdmin
|
||||
|
||||
@admin.register(Category)
|
||||
class CategoryAdmin(BaseModelAdmin, ImportExportModelAdmin):
|
||||
resource_class = CategoryResource
|
||||
list_display = ('name', 'slug', 'created_at', 'is_deleted')
|
||||
list_display = ('name', 'parent', 'slug', 'created_at', 'is_deleted')
|
||||
list_filter = ('created_at', 'is_deleted', SoftDeleteListFilter)
|
||||
search_fields = ('name', 'description')
|
||||
search_fields = ('name', 'description', 'parent__name')
|
||||
prepopulated_fields = {'slug': ('name',)}
|
||||
readonly_fields = ('created_at', 'updated_at', 'deleted_at')
|
||||
|
||||
fieldsets = (
|
||||
('Content', {
|
||||
'fields': ('name', 'slug', 'description')
|
||||
'fields': ('name', 'parent', 'slug', 'description')
|
||||
}),
|
||||
('Metadata', {
|
||||
'fields': ('created_at', 'updated_at')
|
||||
@@ -76,7 +76,7 @@ class PostAdmin(BaseModelAdmin, ImportExportModelAdmin):
|
||||
list_filter = ('status', 'is_featured', 'category', 'tags', 'created_at', 'published_at', SoftDeleteListFilter)
|
||||
search_fields = ('title', 'content', 'author__username')
|
||||
prepopulated_fields = {'slug': ('title',)}
|
||||
filter_horizontal = ('tags',)
|
||||
filter_horizontal = ('tags', 'writers')
|
||||
date_hierarchy = 'published_at'
|
||||
|
||||
fieldsets = (
|
||||
@@ -87,7 +87,7 @@ class PostAdmin(BaseModelAdmin, ImportExportModelAdmin):
|
||||
'fields': ('seo_title', 'seo_description', 'canonical_url', 'og_title', 'og_description', 'og_image', 'noindex', 'focus_keyword', 'reading_time')
|
||||
}),
|
||||
('Metadata', {
|
||||
'fields': ('author', 'category', 'tags', 'status', 'is_featured', 'submitted_at', 'reviewed_at', 'reviewed_by', 'review_note', 'published_at', 'published_by')
|
||||
'fields': ('author', 'writers', 'category', 'tags', 'status', 'is_featured', 'submitted_at', 'reviewed_at', 'reviewed_by', 'review_note', 'published_at', 'published_by')
|
||||
}),
|
||||
('Soft Delete', {
|
||||
'fields': ('is_deleted', 'deleted_at'),
|
||||
@@ -132,8 +132,8 @@ class PostAdmin(BaseModelAdmin, ImportExportModelAdmin):
|
||||
|
||||
@admin.register(Comment)
|
||||
class CommentAdmin(BaseModelAdmin):
|
||||
list_display = ('author', 'post', 'content_preview', 'is_approved', 'created_at')
|
||||
list_filter = ('is_approved', 'created_at', 'post', SoftDeleteListFilter)
|
||||
list_display = ('author', 'post', 'content_preview', 'is_approved', 'is_hidden', 'is_deleted', 'created_at')
|
||||
list_filter = ('is_approved', 'is_hidden', 'created_at', 'post', SoftDeleteListFilter)
|
||||
search_fields = ('content', 'author__username', 'author__last_name', 'author__first_name', 'post__title')
|
||||
readonly_fields = ('content_preview', 'created_at', 'updated_at', 'deleted_at')
|
||||
|
||||
@@ -142,28 +142,35 @@ class CommentAdmin(BaseModelAdmin):
|
||||
'fields': ('post', 'author', 'content')
|
||||
}),
|
||||
('Metadata', {
|
||||
'fields': ('is_approved', 'hidden_by', 'hidden_at', 'moderation_note', 'created_at', 'updated_at')
|
||||
'fields': ('is_approved', 'is_hidden', 'hidden_by', 'hidden_at', 'moderation_note', 'created_at', 'updated_at')
|
||||
}),
|
||||
('Soft Delete', {
|
||||
'fields': ('is_deleted', 'deleted_at'),
|
||||
'fields': ('is_deleted', 'deleted_at', 'deleted_by', 'delete_note'),
|
||||
'classes': ('collapse',)
|
||||
})
|
||||
)
|
||||
actions = BaseModelAdmin.actions + ['approve_comments', 'disapprove_comments']
|
||||
actions = BaseModelAdmin.actions + ['approve_comments', 'hide_comments', 'unhide_comments']
|
||||
|
||||
def content_preview(self, obj):
|
||||
return obj.content[:50] + '...' if len(obj.content) > 50 else obj.content
|
||||
content_preview.short_description = 'Content Preview'
|
||||
|
||||
def approve_comments(self, request, queryset):
|
||||
queryset.update(is_approved=True)
|
||||
queryset.update(is_approved=True, is_hidden=False, hidden_by=None, hidden_at=None, moderation_note='')
|
||||
self.message_user(request, f"Approved {queryset.count()} comments.")
|
||||
approve_comments.short_description = "Approve selected comments"
|
||||
|
||||
def disapprove_comments(self, request, queryset):
|
||||
queryset.update(is_approved=False)
|
||||
self.message_user(request, f"Disapproved {queryset.count()} comments.")
|
||||
disapprove_comments.short_description = "Disapprove selected comments"
|
||||
def hide_comments(self, request, queryset):
|
||||
for comment in queryset:
|
||||
comment.hide(request.user)
|
||||
self.message_user(request, f"Hidden {queryset.count()} comments.")
|
||||
hide_comments.short_description = "Hide selected comments"
|
||||
|
||||
def unhide_comments(self, request, queryset):
|
||||
for comment in queryset:
|
||||
comment.unhide()
|
||||
self.message_user(request, f"Restored {queryset.count()} comments.")
|
||||
unhide_comments.short_description = "Unhide selected comments"
|
||||
|
||||
@admin.register(Like)
|
||||
class LikeAdmin(admin.ModelAdmin):
|
||||
@@ -185,3 +192,24 @@ class PostAssetAdmin(BaseModelAdmin):
|
||||
list_filter = ('file_type', 'mime_type', 'created_at')
|
||||
search_fields = ('title', 'caption', 'alt_text', 'post__title', 'uploaded_by__username')
|
||||
readonly_fields = ('size', 'mime_type', 'created_at', 'updated_at', 'deleted_at')
|
||||
|
||||
|
||||
@admin.register(BlogBanner)
|
||||
class BlogBannerAdmin(BaseModelAdmin):
|
||||
list_display = ('title', 'url', 'is_active', 'sort_order', 'created_at', 'is_deleted')
|
||||
list_filter = ('is_active', 'created_at', 'is_deleted', SoftDeleteListFilter)
|
||||
search_fields = ('title', 'alt_text', 'url')
|
||||
readonly_fields = ('created_at', 'updated_at', 'deleted_at')
|
||||
|
||||
fieldsets = (
|
||||
('Banner', {
|
||||
'fields': ('title', 'alt_text', 'image', 'url', 'is_active', 'sort_order')
|
||||
}),
|
||||
('Metadata', {
|
||||
'fields': ('created_at', 'updated_at')
|
||||
}),
|
||||
('Soft Delete', {
|
||||
'fields': ('is_deleted', 'deleted_at'),
|
||||
'classes': ('collapse',)
|
||||
}),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user